Модуль:Объекты
Материал из Справочника наблюдателя
Var
Модуль содержит функцию Data, предназначенную для обработки данных об отдельном объекте.
- Ключевые параметры
тип = ( УИК / Власти / Сервисы )формат = ( список колонок / карта / карта kml / карта gpx )— формат выдачи (таблица, параметры для multimaps, информация в файлы kml и gpx)url = название страницы— название страницы, в которой расположено обращение к функции Data.- Описания объектов
- Описание каждого объекта состоит из последовательности (неключевых с точки зрения синтаксиса MediaWiki) параметров, каждый из которых имеет вид «
имя : значение», объекты разделяются параметром «-», например:
|-
| номер : 2637
| МО : Реутов
| округ : 18
| адрес : ул. Победы, д. 32 — Школа № 2:ул. Победы, д. 32:55.7683325457,37.847943306
| телефон : {{T|(498) 661-96-75}}
| адрес офиса :
| телефон офиса : {{T|(495) 528-50-53}}
| границы : ул. Победы: 22к3, 30; ул. Некрасова: 2, 4, 6, 10, 12, 16
| численность : 1692
| ПРГ :
| состав :
| КОИБ :
| временный :
| галерея :
|-
- Шаблон:Таблица объектов
- Шаблон:Карта объектов
- Заготовки таблиц
- Карта объектов
- Формирование kml-файла
- Editnotice (вызываются из MediaWiki:Editnotice-0)
Реальные таблицы:
| Чехов (Московская область), 16.02.2014 | УИК | Власти |
| Заборье (Рязанский район Рязанской области), 16.02.2014 | УИК | Власти |
| Кашира, 02.03.2014 | УИК | Власти |
| Киржач, 23.03.2014 | УИК | Власти |
- Карта местности — это показ multimaps
- География/pattern — это заготовка kml
- {геокарта} — шаблон {{геокарта}}
- {геоадрес} — шаблон {{геоадрес}}
Доделать:
- точки с запятой в адресе убийственны для multimaps (см. УИК 1083 в Твери)
- улучшить диагностику ошибок (считать порядковый номер участка и номер параметра внутри участка)
Вышеприведенная документация хранится отдельно ( править | история | скрыть ).
Задавайте категории на странице документации, а не здесь! Показать подстраницы
Задавайте категории на странице документации, а не здесь! Показать подстраницы
local p = {}
local tab = {}
function p.Data (frame)
local addrOld -- true, если непременно старый
-- Разбор параметров
local objT = mw.ustring.lower(v(frame.args['тип']))
if objT == '' then
objT = 'уик'
end
local outF = mw.ustring.lower(v (frame.args['формат']))
if outF =='{{{1}}}' then -- на самой странице. Проверяем качество таблицы
local args = frame.args
local report = ''
local numnam = ''
for key,val in pairs (args) do
if type (key) == 'string' then
if key == 'тип' or key == 'формат' or key == 'url' or key == 'регион' then
elseif mw.ustring.sub (key,1,4) == 'para' then
if mw.ustring.sub (key,1,5) ~= 'para:' or mw.ustring.sub (key,1,6) == 'para: ' then
report = report .. '<br />Ключевой параметр: «<code>' .. key .. ' = ...</code>»' .. ' не должен содержать пробелы вокруг двоеточия'
end
else
report = report .. '<br />Не экранирован знак равенства: «<code><nowiki>' .. key .. '</nowiki><span style="color:red">=</span><nowiki>' .. val .. '</nowiki></code>»'
end
else
local mykey, myval = mw.ustring.match (val, '^([^:]+)%:[\t\r\n\f ]*(.*)$')
if mykey then
mykey = mw.text.trim (mykey)
if mykey == 'para' then
myval = mw.text.trim (myval)
if args ['para:'..myval] then
local mykeyref, myvalref = mw.ustring.match (args ['para:'..myval], '^([^:]+)%:[\t\r\n\f ]*(.*)$')
if not mykeyref then
report = report .. '<br />Не удалось разобрать ключевой параметр «<code>para:' .. myval .. '</code>» (объект ' .. numnam .. '): «<code><nowiki>' .. args ['para:'..myval] .. '</nowiki></code>»'
else
mykey, myval = mykeyref, myvalref
end
else
report = report .. '<br />Несуществующая ссылка «<code>para:' .. myval .. '</code>» (объект ' .. numnam .. ')'
end
end
if (mykey == 'номер') or (mykey == 'наименование') then
numnam = mw.text.trim (v(myval))
elseif mykey == 'адрес' or mykey == 'адрес офиса' then
if mw.ustring.find (myval, ';', 1, true) then
report = report .. '<br />Обнаружен недопустимый символ «;» в адресе: «<code><nowiki>' .. val .. '</nowiki></code>» (объект ' .. numnam .. ')'
end
end
end
end
end
if report ~= '' then
return frame:preprocess ("<br />{{Box|type=serious|text='''Обнаружены ошибки в данных об объектах!'''" .. report
.. '|text-small=Не допускаются точки с запятой в параметре «адрес». Знаки равенства должны быть экранированы двойными фигурными скобками: «<nowiki>{{=}}</nowiki>»}}')
end
end
if (outF == '') or (outF =='{{{1}}}') then
outF = ({['уик']='номер,округ,адрес,телефон,границы',
['власти']='тип,наименование,адрес,телефон,сайты,примечание',
['сервисы']='тип,наименование,адрес,телефон,сайты,примечание',
}) [objT]
end
local url = mw.ustring.lower(v(frame.args['url']))
tabInit ()
-- Формирование заголовков
local result = {}
local columns, geoTemplate
local csvColName, csvColNumber, csvColCount = {}, {}, {} -- заполняем всегда
if mw.ustring.sub(outF,1,5) == 'карта' then
if mw.ustring.sub(outF,-3) == 'kml' then
geoTemplate = '{{ геокарта kml|'
elseif mw.ustring.sub(outF,-3) == 'gpx' then
geoTemplate = '{{ геокарта gpx|'
elseif mw.ustring.sub(outF,-4) == 'json' then
geoTemplate = '{{ геокарта json|'
else
geoTemplate = '{{ multimaps |'
end
elseif outF == 'csv' then
-- csvColName, csvColNumber, csvColCount = {}, {}, {}
else
columns = mw.text.split (outF, '[\t\r\n\f ]*[,;][\t\r\n\f ]*')
local colStyle, colText, colName
local header = ''
for column = 1, #columns do
colName = columns[column]
if tab.headerText [colName] then
colText = tab.headerText [colName]
colStyle = tab.headerStyle [colName]
else
colText = '«'..v(colname)..'»'
colStyle = 'style="background-color:red;"'
end
header = header .. '<th ' .. colStyle .. '>' .. colText .. '</th>'
end
table.insert (result, header)
end
-- Идем по объектам
local info
local infoIdx = 1 -- номер выбираемого параметра (аргумента шаблона)
repeat
local data = {}
local dataYes
repeat
info, infoIdx = frame.args [infoIdx], infoIdx+1;
if info then
info = mw.text.trim (info)
if (info ~= '') and (info ~= '-') then
local key, val = mw.ustring.match (info, '^([^:]+)%:[\t\r\n\f ]*(.*)$')
key = mw.text.trim (v(key))
if key == 'para' then
key, val = mw.ustring.match (frame.args ['para:'..val], '^([^:]+)%:[\t\r\n\f ]*(.*)$')
key = mw.text.trim (v(key))
end
key = mw.ustring.lower(key)
if key ~= '' then
val = mw.text.trim (val)
if val ~= '' then
data [key] = val
dataYes = true
end
else
return 'Некорректные данные «' .. info .. '», параметр ' .. (infoIdx-1)
end
if csvColNumber[key] then
if val ~= '' then
csvColCount[key] = csvColCount[key] + 1
end
else
table.insert (csvColName, key)
csvColNumber[key] = #csvColName
if val ~= '' then
csvColCount[key] = 1
else
csvColCount[key] = 0
end
end
end
end
until not info or info == '-'
if dataYes then
-- перерабатываем адреса
if ne(data ['адрес']) then
data ['адрес'] = addrSplit (data ['адрес'])
end
if ne(data ['адрес офиса']) then
data ['адрес офиса'] = addrSplit (data ['адрес офиса'])
end
if columns then -- таблица
local res = ''
for column = 1, #columns do
local colName = columns[column]
local dataT, dataColumn = tab.dataType[colName], data[colName]
if not dataT then
if not dataColumn then
dataColumn = ''
end
elseif type(dataT) == 'function' then
dataColumn = dataT (dataColumn, data)
else
dataColumn = ''
end
res = res .. '<td ' .. v(tab.dataStyle[colName]) .. '>' .. dataColumn .. '</td>'
end
table.insert(result,res)
elseif outF == 'csv' then
table.insert(result,data) -- А не по ссылке ли здесь всё получится?
else
-- карты. УИК
if data ['адрес'][7] ~= 'н' then
if objT == 'уик' then
local numb = mw.ustring.sub ('0000' .. normUIK (data['номер']),-4)
table.insert (result, geoTemplate .. 'УИК|УИК ' .. data['номер'] .. '|' .. bQ(data ['адрес'][1]) .. '|' .. data ['адрес'][2] .. '|' .. data ['адрес'] [3] .. '|' .. data ['адрес'] [4]
.. '|/E/' .. string.sub (numb,1,1) .. '/uik' .. numb .. '-e.png|' .. data ['адрес'][7] .. '}}')
-- objN = objN +1
else
local tipus = v(data['тип'])
local icon = tab.icoName [tipus]
if icon then
icon = '|/E/gov/' .. icon .. '-e.png'
else
icon = '|'
end
table.insert (result, geoTemplate .. (data['метка'] or tipus) .. '|' .. v (data['наименование']) .. '|' .. bQ(data ['адрес'][1]) .. '|' .. data ['адрес'][2] .. '|' .. data ['адрес'] [3] .. '|' .. data ['адрес'] [4]
.. icon .. '|' .. data ['адрес'][7] .. '}}')
-- objN = objN +1
end
end
end
end
until not info;
-- завершающие операции
if columns then
if url ~= '' then
url ='<caption class=plainlinks style="font-size:80%; line-height:110%; text-align:right;">'
.. 'Сведения об объектах вносятся '
.. ' [{{fullurl:{{{url|{{FULLPAGENAME}}/{{{тип|УИК}}}}}}|action=edit}} здесь]. '
.. 'Скачать [//www.nablawiki.ru/images/ArticleToFile/{{urlencode:{{BASEPAGENAME}} - {{{тип|УИК}}}.csv|PATH}} файл в формате csv]'
.. '([[Как работать с таблицей объектов в формате csv|?]])</caption>'
end
return frame:preprocess ('<table class="wikitable sortable">' .. url
.. '<tr>' .. table.concat (result, '</tr><tr>') .. '</tr></table>')
elseif outF == 'csv' then
local res = ''
for j = 1, #csvColName do
if csvColCount[csvColName[j]] ~= 0 then
if csvColName[j] == 'адрес' or csvColName[j] == 'адрес офиса' then
if addrOld then
res = res .. '"' .. csvColName[j] .. ' (текст)","' .. csvColName[j] .. ' (дом)","' .. csvColName[j] .. ' (гео)","' .. csvColName[j] .. ' (вид)",'
else
res = res .. '"' .. csvColName[j] .. ' (дом)","' .. csvColName[j] .. ' (орг)","' .. csvColName[j] .. ' (гео)","' .. csvColName[j] .. ' (вид)",'
end
-- elseif csvColName[j] == 'телефон' or csvColName[j] == 'телефон офиса' then
-- res = res .. '"' .. csvColName[j] .. '",'
else
res = res .. '"' .. csvColName[j] .. '",'
end
end
end
res = res .. '\n'
for i = 1, #result do
for j = 1, #csvColName do
if csvColCount[csvColName[j]] ~= 0 then
if result[i][csvColName[j]] then
if csvColName[j] == 'адрес' or csvColName[j] == 'адрес офиса' then
local aa
if addrOld then
aa = 2
res = res .. '"' .. dQ(result[i][csvColName[j]] [1]) .. '","' .. dQ(result[i][csvColName[j]] [2]) .. '",'
-- .. result[i][csvColName[j]] [3] .. ',' .. result[i][csvColName[j]] [4] .. '",'
else
aa = 5
res = res .. '"' .. dQ(result[i][csvColName[j]] [5]) .. '","' .. dQ(result[i][csvColName[j]] [6]) .. '",'
-- .. result[i][csvColName[j]] [3] .. ',' .. result[i][csvColName[j]] [4] .. '",'
end
if result[i][csvColName[j]] [3] ~= '' then
res = res .. '"' .. result[i][csvColName[j]] [3] .. ',' .. result[i][csvColName[j]] [4] .. '",'
else
res = res .. '"' .. '{{#yandexgeo:{{#var:Геобаза}}, ' .. result[i][csvColName[j]] [aa] .. '|maps}}' .. '",'
end
if result[i][csvColName[j]] [7] ~= 'д' then
res = res .. '"' .. result[i][csvColName[j]] [7] .. '",'
else
res = res .. '"",'
end
else
res = res .. '"' .. dQ(result[i][csvColName[j]]) .. '",'
end
else
if csvColName[j] == 'адрес' or csvColName[j] == 'адрес офиса' then
res = res .. '"","","","",'
else
res = res .. '"",'
end
end
end
end
res = res .. '\n'
end
return frame:preprocess (res)
else
return frame:preprocess (table.concat (result))
end
end
function addrSplit (addr)
local a = mw.text.split (addr..'::', '[\t\r\n\f ]*:[\t\r\n\f ]*')
local x = {}
if a[1] == '' then --новый формат
x = { a[2] or '', a[3] or '', a[4] or ''}
if x[2] == '' then
a[1] = x[1]
else
a[1] = x[1] .. ' — ' .. x[2]
end
a[3] = x[3]
a[4] = a[5]
elseif e (a[2]) then
x[1] = a[1]
x[2] = ''
else
if mw.ustring.sub (a[1],1,mw.ustring.len(a[2])) == a[2] then
x[1] = a[2]
x[2] = mw.text.trim(mw.ustring.sub (a[1],mw.ustring.len(a[2])+1,-1))
if mw.ustring.sub (x[2], 1, 2) == '— ' then
x[2] = mw.text.trim (mw.ustring.sub (x[2], 3, -1))
end
else
addrOld = true
a[1] = '! ' .. a[1]
x[1] = ''
x[2] = ''
end
end
local c = {'', ''}
if ne(a[3]) then
c = mw.text.split (a[3]..',', '[\t\r\n\f ]*,[\t\r\n\f ]*')
end
return { a[1], a[2], c[1], c[2], x[1], x[2], mw.ustring.lower (mw.ustring.sub ((a[4] or '') .. 'да',1,1)) }
end
function e (t)
return (t or '') == ''
end
function ne (t)
return (t or '') ~= ''
end
function v (t)
return (t or '')
end
function normUIK (numbUIK)
return ( string.gsub (numbUIK, '^0*([0-9]+)[%-/]?([0-9]*)$','%1%2'))..''
end
function dQ (s)
return mw.ustring.gsub (s, '"', '""')
end
function bQ (s)
return mw.ustring.gsub (s, '"', '\\"')
end
function tabInit ()
tab.headerStyle = {
['номер'] = 'style="width:4en;"';
['мо'] = '';
['округ'] = 'style="width:3en;"';
['коиб'] = 'style="width:2en;"';
['временный'] = 'style="width:2en;"';
['численность'] = 'style="width:6en;"';
['прг'] = '';
['адрес'] = 'class=unsortable';
['телефон'] = 'class=unsortable';
['адрес офиса'] = 'class=unsortable';
['телефон офиса'] = 'class=unsortable';
['границы'] = 'class=unsortable';
['номер0412'] = 'style="width:4en; font-size:75%; line-height:80%"';
['итог0412'] = 'style="width:4en; font-size:75%; line-height:80%"';
['явка0412'] = 'style="width:4en; font-size:75%; line-height:80%"';
['дом0412'] = 'style="width:4en; font-size:75%; line-height:80%"';
['числ0412'] = 'style="width:4en; font-size:75%; line-height:80%"';
['номер0403'] = 'style="width:4en; font-size:75%; line-height:80%"';
['итог0403'] = 'style="width:4en; font-size:75%; line-height:80%"';
['явка0403'] = 'style="width:4en; font-size:75%; line-height:80%"';
['дом0403'] = 'style="width:4en; font-size:75%; line-height:80%"';
['числ0403'] = 'style="width:4en; font-size:75%; line-height:80%"';
['галерея'] = 'style="width:2en;"';
['тип'] = 'style="width:3en; border-right:0px;"';
['наименование'] = '';
['метка'] = '';
['сайты'] = 'class=unsortable';
['примечание'] = 'class=unsortable';
['#явка'] = '';
['#досрочно'] = '';
['#дома'] = '';
['#власть'] = '';
['#явка%'] = '';
['#досрочно%'] = '';
['#дома%'] = '';
['#власть%'] = '';
}
tab.headerText = {
['номер'] = 'УИK';
['мо'] = 'МО';
['округ'] = '<small>округ</small>';
['коиб'] = '<small>KОИБ</small>';
['временный'] = '<small>{{подсказка|вр.|участок, созданный для временно пребывающих}}</small>';
['численность'] = 'изб.';
['прг'] = '{{подсказка|ПPГ|число членов комиссии с правом решающего голоса}}';
['адрес'] = 'адрес помещения';
['телефон'] = 'телефон';
['адрес офиса'] = 'адрес офиса';
['телефон офиса'] = 'тел. офиса';
['границы'] = 'границы избирательного участка';
['номер0412'] = '04.12<br />№ УИК';
['итог0412'] = '04.12<br />за ЕР';
['явка0412'] = '04.12<br />явка';
['дом0412'] = '04.12<br />дома';
['числ0412'] = '04.12<br />число';
['номер0403'] = '04.03<br />№ УИК';
['итог0403'] = '04.03<br />Путин';
['явка0403'] = '04.03<br />явка';
['дом0403'] = '04.03<br />дома';
['числ0403'] = '04.03<br />число';
['галерея'] = '<small>фото</small>';
['тип'] = ' ';
['наименование'] = 'наименование органа';
['метка'] = 'сокр.';
['сайты'] = 'сайт';
['примечание'] = 'примечание';
['#явка'] = 'явка';
['#досрочно'] = 'доср.';
['#дома'] = 'дома';
['#власть'] = 'власть';
['#явка%'] = 'явка';
['#досрочно%'] = 'доср.';
['#дома%'] = 'дома';
['#власть%'] = 'власть';
}
tab.dataStyle = {
['номер'] = 'class=plainlinks style="text-align:center; font-weight:bold; background-color:#f2f2f2;"';
['мо'] = 'style="font-size:83%; line-height:95%;"';
['округ'] = 'style="text-align:center; "';
['коиб'] = 'style="text-align:center; "';
['временный'] = 'style="text-align:center; "';
['численность'] = 'style="text-align:right; background-color:Beige;"';
['прг'] = 'style="text-align:center; "';
['адрес'] = 'style="font-size:92%; line-height:95%;"';
['телефон'] = '';
['адрес офиса'] = 'style="font-size:92%; line-height:95%;"';
['телефон офиса'] = '';
['границы'] = 'style="font-size:83%; line-height:95%;"';
['номер0412'] = 'style="text-align:center; font-weight:bold; background-color:#f2f2f2;"';
['итог0412'] = 'style="text-align:right; "';
['явка0412'] = 'style="text-align:right; background-color:Ivory; "';
['дом0412'] = 'style="text-align:right; background-color:Honeydew; "';
['числ0412'] = 'style="text-align:right; background-color:Beige;"';
['номер0403'] = 'style="text-align:center; font-weight:bold; background-color:#f2f2f2;"';
['итог0403'] = 'style="text-align:right; "';
['явка0403'] = 'style="text-align:right; background-color:Ivory; "';
['дом0403'] = 'style="text-align:right; background-color:Honeydew; "';
['числ0403'] = 'style="text-align:right; background-color:Beige;"';
['галерея'] = '';
['тип'] = 'style="border-right:0px;"';
['наименование'] = '';
['метка'] = '';
['сайты'] = 'style="font-size:83%; line-height:95%;"';
['примечание'] = 'style="font-size:83%; line-height:95%;"';
['#явка'] = 'style="text-align:right; background-color:Ivory; "';
['#досрочно'] = 'style="text-align:right; background-color:Ivory; "';
['#дома'] = 'style="text-align:right; background-color:Ivory; "';
['#власть'] = 'style="text-align:right; background-color:Ivory; "';
['#явка%'] = 'style="text-align:right; background-color:Ivory; "';
['#досрочно%'] = 'style="text-align:right; background-color:Ivory; "';
['#дома%'] = 'style="text-align:right; background-color:Ivory; "';
['#власть%'] = 'style="text-align:right; background-color:Ivory; "';
}
tab.icoName = {
['ИК'] = 'ik';
['ТИК'] = 'tik';
['ИКМО'] = 'ikmo';
['полиция'] = 'ovd';
['прокуратура'] = 'proc';
['СК'] = 'ck';
['суд'] = 'sud2';
['адм'] = 'adm2';
}
tab.dataType = {}
tab.dataType['галерея']=function (s)
if (not s) or (s == '') then
return ''
else
return '[[Файл:Фотофайлы.png|link=' .. s .. ']]'
end
end
tab.dataType['номер']=function (s,column)
if (not s) or (s == '') then
return ''
else
local txt = '[https://www.wikiuiki.org/ik/{{#var:RegCode}}-uik-' .. normUIK (s) .. ' ' .. s .. ']';
-- [{{#invoke:Campaign|RegGASnew|{{#if:{{{регион|}}}|{{{регион}}}|{{PAGENAME}}}}}}/ik ТИКи]
if (column ['гас'] or '') ~= '' then
txt = txt .. ' [' .. column ['гас'] .. ' <sup><span style="color:red">§</span></sup>]';
end
return txt
end
end
tab.dataType['адрес']=function (s)
if (not s) or (s == '') then
return ''
else
return '{{геоадрес|' .. table.concat(s,'|') .. '}}';
end
end
tab.dataType['адрес офиса']=function (s)
if (not s) or (s == '') then
return ''
else
return '{{геоадрес|' .. table.concat(s,'|') .. '}}';
end
end
tab.dataType['#явка%']=function (s, column)
return (string.format('%4.1f', tonumber (column ['#явка']) / tonumber (column ['численность']) * 100) .. '%');
end
tab.dataType['#досрочно%']=function (s, column)
return (string.format('%4.1f', tonumber (column ['#досрочно']) / tonumber (column ['численность']) * 100) .. '%');
end
tab.dataType['#дома%']=function (s, column)
return (string.format('%4.1f', tonumber (column ['#дома']) / tonumber (column ['численность']) * 100) .. '%');
end
tab.dataType['#власть%']=function (s, column)
return (string.format('%4.1f', tonumber (column ['#власть']) / tonumber (column ['численность']) * 100) .. '%');
end
tab.dataType['телефон']=function (s)
if (not s) or (s == '') then
return ''
elseif mw.ustring.sub(s,1,1) == '<' then
return s
else
return '{{T|' .. s .. '}}'
end
end
tab.dataType['телефон офиса']=function (s)
if (not s) or (s == '') then
return ''
elseif mw.ustring.sub(s,1,1) == '<' then
return s
else
return '{{T|' .. s .. '}}'
end
end
end
return p