Модуль:CargoObjectDump
Материал из Справочника наблюдателя
Описание модуля[]
Документация отсутствует!
Вы можете создать документацию ( создать ).
Задавайте категории на странице документации, а не здесь! Показать подстраницы
Задавайте категории на странице документации, а не здесь! Показать подстраницы
local p = {}
local global = mw.ext.luaglobal
local cargo = mw.ext.cargo;
local Geobase = global.get( 'Geobase' )
local Fields = global.get( 'Fields' )
local Region = global.get( 'RegionCode' )
local GeoParam = global.get( 'GeoParam' )
global.strict( true )
local function collectObjects( ctg )
local basename = mw.title.getCurrentTitle().baseText
local collectPage = mw.title.new( basename .. '/Сборка' )
local bases, subs = {}, {}
if collectPage.id ~= 0 then
local content = mw.text.trim( collectPage:getContent() or '' )
content = mw.text.split( content, '[\t\f ]*[\r\n]+[\t\f ]*' )
for _, val in pairs( content ) do
if val ~= '' then
local z = mw.ustring.sub( val, 1, 1 )
if val == '/' then
subs[#subs+1] = ''
elseif z == '/' then
subs[#subs+1] = val
elseif z == ':' then
bases[#bases+1] = basename .. val
else
bases[#bases+1] = val
end
end
end
end
if #bases == 0 then
bases = { basename }
end
if ctg then
subs = { '/' .. ctg }
elseif #subs == 0 then
subs = { '/УИК', '/Власти', '/Сервисы' }
end
local basesCounter, subsCounter = 1, 0
return function ()
subsCounter = subsCounter + 1
if subsCounter > #subs then
basesCounter = basesCounter + 1
if basesCounter > #bases then
return nil
end
subsCounter = 1
end
return bases[basesCounter] .. subs[subsCounter] -- , mw.ustring.sub( subs[subsCounter], 2, -1 )
end,
bases --- еще надо понять, что мы хотим
end
local function normUIK (numbUIK)
return string.gsub ( '' .. numbUIK, '^0*([0-9]+)[%-/]?([0-9]*)$', '%1%2' )
end
local prec_color = { '#CCC', '#3366BB', '#ff9900', 'red' }
local function showAddr ( row, prefix, alt )
local addr, org, lat, lon, prec, show =
row[prefix..'_addr'], row[prefix..'_org'], row[prefix..'_geo__lat'],
row[prefix..'_geo__lon'], tonumber( row[prefix..'_geo_p'] ), row[prefix..'_geo_s']
local result = addr
if ( addr or '' ) == '' then
return ''
end
if org ~= '' then
result = result .. ' — ' .. org
end
if alt then
result = result .. ' <span style="color:#746963; font-style:italic">(' .. alt .. ')</span>'
end
local marker
if prec > 4 then
marker = 'pin'
prec = prec - 4
else
marker = 'marker-alt'
end
result = result .. ' [http://m.nablawiki.ru/?' .. GeoParam
.. '&addressSpecial=' .. mw.uri.encode( addr, 'PATH' )
if ( lat or 0 ) ~= 0 then
result = result .. '&latlon=' .. lat .. ',' .. lon
prec = prec_color[ prec ]
else
prec = 'red'
end
result = result .. ' <span class="fas fa-map-' .. marker .. '" style="color:' .. prec
.. '" title="на карте"></span>]'
return result
end
local function compositeAddr ( row )
local addr, org = row['room_addr'], row['room_org']
local addrO, orgO = row['office_addr'], row['office_org']
if ( addrO or '' ) == '' then
return showAddr( row, 'room' )
end
if addr ~= addrO then
return showAddr( row, 'room' ) .. '<br><span style="color:#746963; font-style:italic">'
.. showAddr( row, 'office' ) .. '</span>'
end
if org == orgO then
return showAddr( row, 'room' )
end
return showAddr( row, 'room', orgO )
end
local function compositePhone( row )
local room, offi = row.room_phone, row.office_phone
if room == offi then
return room
end
return room .. '<br><span style="color:#746963; font-style:italic">' .. offi .. '</span>'
end
local tabC = {
['номер'] = { 'style="width:4en;"',
'УИK',
'style="text-align:center; font-weight:bold;"',
function ( row )
local s = row.number
if s == '' then
return ''
else
local txt = '[https://www.wikiuiki.org/ik/' .. Region .. '-uik-' .. normUIK (s) .. ' ' .. s .. ']';
if (row.gas or '') ~= '' then
txt = txt .. ' [' .. row.gas .. ' <sup><span style="color:red">§</span></sup>]';
end
if row.temp ~= '' then
txt = '{{подсказка|<i>' .. txt .. '</i>|временный участок}}'
end
return txt
end
end,
},
['мо'] = { '',
'МО',
'style="font-size:83%; line-height:95%;"',
'mun',
},
['округ'] = { 'style="width:3en;"',
'<small>округ</small>',
'style="text-align:center;"',
'district',
},
['коиб'] = { 'style="width:2en;"',
'<small>KОИБ</small>',
'style="text-align:center;"',
'koib',
},
-- ['временный'] = { 'style="width:2en;"',
-- '<small>{{подсказка|вр.|участок, созданный для временно пребывающих}}</small>',
-- 'style="text-align:center;"',
-- },
['численность'] = { 'style="width:4en;"',
'изб.',
'style="text-align:right;"',
'quantity',
},
['прг'] = { '',
'{{подсказка|ПPГ|число членов комиссии с правом решающего голоса}}',
'style="text-align:center;"',
'members',
},
['адрес'] = { 'class=unsortable',
'адрес помещения',
'style="font-size:92%; line-height:95%;"',
function ( row )
return showAddr( row, 'room' )
end
},
['адреса'] = { 'class=unsortable',
'адрес помещения, <i>адрес офиса</i>',
'style="font-size:92%; line-height:95%;"',
compositeAddr,
},
['телефон'] = { 'class=unsortable',
'телефон',
'',
'room_phone',
},
['телефоны'] = { 'class=unsortable',
'телефоны',
'',
compositePhone,
},
['адрес офиса'] = { 'class=unsortable',
'адрес офиса',
'style="font-size:92%; line-height:95%;"',
function ( row )
return showAddr( row, 'office' )
end
},
['телефон офиса'] = { 'class=unsortable',
'тел. офиса',
'',
'office_phone',
},
['границы'] = { 'class=unsortable',
'границы избирательного участка',
'style="font-size:83%; line-height:95%;"',
'border',
},
['тип'] = { 'style="width:3en; border-right:0px;"',
' ',
'style="font-size:83%; line-height:95%;"',
'label',
},
['наименование'] = { '',
'наименование органа',
'',
'name',
},
-- ['метка'] = { '',
-- 'сокр.',
-- },
['сайты'] = { 'class=unsortable',
'сайты',
'style="font-size:83%; line-height:95%;"',
'site',
},
['примечание'] = { 'class=unsortable',
'примечание',
'style="font-size:83%; line-height:95%;"',
'addendum',
},
['#явка'] = { '',
'явка',
'',
'x_turnout',
},
['#досрочно'] = { '',
'доср.',
'',
'x_before',
},
['#дома'] = { '',
'дома',
'',
'x_home',
},
['#власть'] = { '',
'власть',
'',
'x_loyal',
},
['#явка%'] = { '',
'явка',
'',
function ( row )
if (row.quantity or 0) ~= 0 then
return string.format('%4.1f', tonumber (row.x_turnout) / tonumber (row.quantity) * 100) .. '%'
else
return ''
end
end,
},
['#досрочно%'] = { '',
'доср.',
'',
function ( row )
if (row.quantity or 0) ~= 0 then
return string.format('%4.1f', tonumber (row.x_before) / tonumber (row.quantity) * 100) .. '%'
else
return ''
end
end,
},
['#дома%'] = { '',
'дома',
'',
function ( row )
if (row.quantity or 0) ~= 0 then
return string.format('%4.1f', tonumber (row.x_home) / tonumber (row.quantity) * 100) .. '%'
else
return ''
end
end,
},
['#власть%'] = { '',
'власть',
'',
function ( row )
if (row.quantity or 0) ~= 0 then
return string.format('%4.1f', tonumber (row.x_loyal) / tonumber (row.quantity) * 100) .. '%'
else
return ''
end
end,
},
}
function p.tab( frame )
--[=[
Может вызываться на странице с объектами или на сторонней странице
Родную страницу распознаем либо по наличию глобальных Fields либо Geobase
Типы и метки надо объединить(?):
ИКМО(поселение) — ТИК/ИКМО(район) — ГИК — ИКСРФ
ОВД — МО МВД — ГорОВД — (Г)УВД СРФ
Адм поселения — района — города — субъекта
---
Параметры:
* категория=текст (по умолчанию УИК, иначе ищем страницу «/текст»)
* список полей (при пустом берем Fields, при пустом Fields берем умолчание для предусмотренных категорий, иначе только наименование)
--]=]
local args = frame:getParent().args
local ctg = args['категория'] or 'УИК'
local list = mw.text.trim( mw.ustring.lower( args[1] or '' ) )
if list == '' then
if true then -- not next( Fields ) then
if ctg == 'УИК' then
list = { 'номер', 'округ', 'адрес', 'телефон' ,'границы' }
elseif ctg == 'Власти' or ctg == 'Сервисы' then
list = { 'тип', 'наименование', 'адрес', 'телефон', 'сайты', 'примечание' }
else
list = { 'тип', 'наименование', 'адрес', 'телефон', 'сайты', 'примечание' }
end
end
else
list = mw.text.split( list, '[\t\r\n\f ]*,[\t\r\n\f ]*' )
end
local result = { { '' }, '<table class="wikitable sortable>', { '' } }
local editInfo = {}
local nopageInfo = {}
-- result[#result+1] = '<caption style="font-size:80%; line-height:110%; text-align:right;">'
-- .. 'Сведения об объектах вносятся '
-- .. ' [{{fullurl:' .. mw.title.getCurrentTitle().text .. '/' .. ctg
-- .. '|action=edit&editintro=Избирательные_кампании/Объекты/' .. ctg .. '/editnotice'
-- .. '}} здесь]. '
-- .. 'Скачать [//www.nablawiki.ru/images/ArticleToFile/{{urlencode:{{BASEPAGENAME}} - '
-- .. ctg .. '.csv|PATH}} файл в формате csv]'
-- .. '([[Как работать с таблицей объектов в формате csv|?]])</caption><tr>'
result[#result+1] = '<tr>'
for _, col in ipairs( list ) do
local z = tabC[col]
if z then
z = '<th ' .. z[1] .. '>' .. z[2] .. '</th>'
else
z = '<th style="background-color:red">' .. col .. '</th>'
end
result[#result+1] = z
end
result[#result+1] = '</tr>'
local wasPages
-- local collectObjects = collectObjects( ctg ) -- переопределили на собственно итератор
for finam in collectObjects( ctg ) do
wasPages = true
local pid = mw.title.new( finam ).id
local tmp = cargo.query( 'ObjectsPage', '_pageID,geobase,geoparam,region',
{ where = '_pageID=' .. pid } )
if #tmp == 0 then
nopageInfo[#nopageInfo+1] = frame:preprocess(
'{{Доделать|доделать|header=Страница «'
.. finam .. '» еще не создана.'
.. '|Чтобы создать страницу и увидеть инструкцию по ее наполнению, нажмите ['
.. '{{fullurl:' .. finam
.. '|action=edit&preload=Избирательные_кампании/Объекты/' .. ctg .. '/pattern'
.. '&editintro=Избирательные_кампании/Объекты/' .. ctg .. '/editnotice'
.. '}} сюда]}}[[Категория:Незаполненная таблица]]' )
else
local shortname = mw.ustring.match( finam, ':([^:]+)/[^/]+$' )
if Fields or not shortname then
shortname = 'здесь'
end
editInfo[#editInfo+1] = '[' .. tostring( mw.uri.fullUrl( finam, {
action = 'edit',
editintro = 'Избирательные_кампании/Объекты/' .. ctg .. '/editnotice',
} ) )
.. ' ' .. shortname .. ']'
tmp = tmp[1]
Geobase = tmp.geobase
GeoParam = tmp.geoparam
Region = tmp.region
local cQuery = cargo.query( 'Objects',
'_pageID, number, mun, gas, district, koib, temp, quantity, members, room_addr, room_org, '
.. 'room_geo__lat, room_geo__lon, room_geo_s, room_geo_p,room_phone, '
.. 'office_addr, office_org, office_geo__lat, office_geo__lon, office_geo_p, office_geo_s, '
.. 'office_phone, border, addendum, x_turnout, x_before, x_home, x_loyal, '
.. 'name, site, label',
{
where = '_pageID=' .. pid,
limit = 1000,
}
)
for _, row in ipairs( cQuery ) do
result[#result+1] = '<tr>'
for _, col in ipairs( list ) do
local z = tabC[col]
result[#result+1] = '<td ' .. z[3] .. '>'
if type( z[4] ) == 'function' then
result[#result+1] = z[4](row) .. '</td>'
else
result[#result+1] = mw.text.decode( row[z[4]] ) .. '</td>'
end
end
result[#result+1] = '</tr>'
end
end
end
if not wasPages then
return 'Нет ничего!'
end
result[1] = table.concat( nopageInfo, '\n' )
if Fields then
result[3] = '<caption style="font-size:80%; line-height:110%; text-align:right;">'
.. 'Скачать [//www.nablawiki.ru/images/ArticleToFile/{{urlencode:{{BASEPAGENAME}} - '
.. ctg .. '.csv|PATH}} файл в формате csv]'
.. '([[Как работать с таблицей объектов в формате csv|?]])</caption>'
else
result[3] = '<caption style="font-size:80%; line-height:110%; text-align:right;">'
..'Редактирование сведений об объектах: '
.. table.concat (editInfo, ' • ') .. '</caption>'
end
result[#result+1] = '</table>'
return frame:preprocess( table.concat(result) )
end
local icoName = {
['ИК'] = 'ik';
['ТИК'] = 'tik';
['ИКМО'] = 'ikmo';
['полиция'] = 'ovd';
['прокуратура'] = 'proc';
['СК'] = 'ck';
['суд'] = 'sud2';
['адм'] = 'adm2';
}
local function dQ (s)
return mw.ustring.gsub ( mw.text.decode( s ), '"', '""')
end
local function bQ (s)
return mw.ustring.gsub (s, '"', '\\"')
end
local function pointName( row )
if (row.number or '') ~= '' then
return 'УИК ' .. bQ( row.number )
else
return bQ( row.name )
end
end
local function pointAddr( row )
if row.room_org == '' then
return bQ( row.room_addr )
else
return bQ( row.room_addr .. ' — ' .. row.room_org )
end
end
local function pointIcon( row )
if (row.number or '') ~= '' then
local numb = mw.ustring.sub ('0000' .. normUIK (row.number),-4)
return 'http://www.nablawiki.ru/images/NablaIcons/E/' .. string.sub (numb,1,1) .. '/uik' .. numb .. '-e.png'
else
local icon =icoName[row.label]
if icon then
return 'http://www.nablawiki.ru/images/NablaIcons/E/gov/' .. icon .. '-e.png'
else
return ''
end
end
end
function p.kml( frame )
local result = {}
for finam in collectObjects() do
local pid = mw.title.new( finam ).id
if pid ~= 0 then
local cQuery = cargo.query( 'Objects',
'_pageID, number, mun, gas, district, koib, temp, quantity, members, room_addr, room_org, '
.. 'room_geo__lat, room_geo__lon, room_geo_s, room_geo_p,room_phone, '
.. 'office_addr, office_org, office_geo__lat, office_geo__lon, office_geo_p, office_geo_s, '
.. 'office_phone, border, addendum, x_turnout, x_before, x_home, x_loyal, '
.. 'name, site, label',
{
where = '_pageID=' .. pid,
limit = 1000,
}
)
if #cQuery ~= 0 then
result[#result+1] = [[
<Folder>
<name>]] .. finam .. [[</name>
<description>Информация для выборов</description>]]
for _,row in ipairs( cQuery ) do
result[#result+1] = ' <Placemark>'
result[#result+1] = ' <name>' .. pointName( row ) .. '</name>'
result[#result+1] = ' <description>' .. pointAddr( row ) .. '</description>'
result[#result+1] = [[
<Point>
<coordinates>]] .. row.room_geo__lon .. ',' .. row.room_geo__lat .. [[</coordinates>
</Point>
<Style>
<IconStyle>
<Icon>
<href>]] .. pointIcon( row ) .. [[</href>
</Icon>
<hotSpot x="11" y="0" xunits="pixels" yunits="pixels" />
</IconStyle>
</Style>
</Placemark>]]
end
result[#result+1] = ' </Folder>'
end
end
end
return table.concat( result, '\n' )
end
function p.gpx( frame )
local result = {}
for finam in collectObjects() do
local pid = mw.title.new( finam ).id
if pid ~= 0 then
local cQuery = cargo.query( 'Objects',
'_pageID, number, mun, gas, district, koib, temp, quantity, members, room_addr, room_org, '
.. 'room_geo__lat, room_geo__lon, room_geo_s, room_geo_p,room_phone, '
.. 'office_addr, office_org, office_geo__lat, office_geo__lon, office_geo_p, office_geo_s, '
.. 'office_phone, border, addendum, x_turnout, x_before, x_home, x_loyal, '
.. 'name, site, label',
{
where = '_pageID=' .. pid,
limit = 1000,
}
)
if #cQuery ~= 0 then
for _,row in ipairs( cQuery ) do
result[#result+1] = ' <wpt lat="' .. row.room_geo__lat .. '" lon="' .. row.room_geo__lon .. '">'
result[#result+1] = ' <name>' .. pointName( row ) .. '</name>'
result[#result+1] = ' <desc>' .. pointAddr( row ) .. '</desc>'
-- result[#result+1] = ' <cmt>' .. pointAddr( row ) .. '</cmt>'
result[#result+1] = ' </wpt>'
end
end
end
end
return table.concat( result, '\n' )
end
function p.json( frame )
local result = {}
for finam in collectObjects() do
local pid = mw.title.new( finam ).id
if pid ~= 0 then
local cQuery = cargo.query( 'Objects',
'_pageID, number, mun, gas, district, koib, temp, quantity, members, room_addr, room_org, '
.. 'room_geo__lat, room_geo__lon, room_geo_s, room_geo_p,room_phone, '
.. 'office_addr, office_org, office_geo__lat, office_geo__lon, office_geo_p, office_geo_s, '
.. 'office_phone, border, addendum, x_turnout, x_before, x_home, x_loyal, '
.. 'name, site, label',
{
where = '_pageID=' .. pid,
limit = 1000,
}
)
if #cQuery ~= 0 then
for _,row in ipairs( cQuery ) do
local outside = ''
if row.room_geo_s ~= 0 then
outside = ', "outside": 1'
end
result[#result+1] = [[
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": []] .. row.room_geo__lon .. ',' .. row.room_geo__lat .. [[]
},
"properties": {]]
-- show --
result[#result+1] = ' "name": "' .. pointName( row ) .. '",'
result[#result+1] = ' "description": "' .. pointAddr( row ) .. '",'
result[#result+1] = ' "icon": {'
result[#result+1] = ' "iconUrl": "' .. pointIcon( row ) .. '",'
result[#result+1] = [[
"iconSize": [39, 30],
"iconAnchor": [11, 30],
"popupAnchor": [9, -30]
}]] .. outside .. [[
}
},]]
end
end
end
end
return table.concat( result, '\n' )
end
function p.csv( frame )
local paname = mw.title.getCurrentTitle().text
local pid = mw.title.new( paname ).id
if pid == 0 then
return nil
end
local cQuery = cargo.query( 'Objects',
'_pageID, number, mun, gas, district, koib, temp, quantity, members, room_addr, room_org, '
.. 'room_geo__lat, room_geo__lon, room_geo_s, room_geo_p,room_phone, '
.. 'office_addr, office_org, office_geo__lat, office_geo__lon, office_geo_p, office_geo_s, '
.. 'office_phone, border, addendum, x_turnout, x_before, x_home, x_loyal, '
.. 'name, site, label',
{
where = '_pageID=' .. pid,
limit = 1000,
}
)
if #cQuery == 0 then
return nil
end
local fieldsSeq = {
label = { 10, 'тип' },
number = { 20, 'номер' },
gas = { 30, 'ГАС' },
temp = { 40, 'временный' },
name = { 50, 'наименование' },
mun = { 60, 'МО' },
district = { 70, 'округ' },
koib = { 80, 'КОИБ' },
members = { 90, 'ПРГ' },
room_addr = { 100, 'адрес (дом)' },
room_org = { 110, 'адрес (орг)' },
room_geo__lat = { 120, 'адрес (широта)' },
room_geo__lon = { 130, 'адрес (долгота)' },
room_geo_p = { 140, 'адрес (точность)' },
room_geo_s = { 150, 'адрес (показ)' },
room_phone = { 160, 'телефон' },
office_addr = { 170, 'адрес офиса (дом)' },
office_org = { 180, 'адрес офиса (орг)' },
office_geo__lat = { 190, 'адрес офиса (широта)' },
office_geo__lon = { 200, 'адрес офиса (долгота)' },
office_geo_p = { 210, 'адрес офиса (точность)' },
office_geo_s = { 220, 'адрес офиса (показ)' },
office_phone = { 230, 'телефон офиса' },
border = { 240, 'границы' },
quantity = { 250, 'численность' },
x_turnout = { 260, '#явка' },
x_before = { 270, '#досрочно' },
x_home = { 280, '#дома' },
x_loyal = { 290, '#власть' },
site = { 300, 'сайты' },
addendum = { 310, 'примечание' },
}
local columns, xc = {}, {}
for _,row in ipairs( cQuery ) do
row._pageID = nil
for col, value in pairs( row ) do
if (value or '') ~= '' and not xc[col] then
xc [col] = true
columns[#columns+1] = col
end
end
end
table.sort( columns, function ( a, b )
return fieldsSeq[a][1] < fieldsSeq[b][1]
end )
-- local result = { table.concat( columns, ',' ) }
local x = {}
for i, col in ipairs( columns ) do
x[i] = fieldsSeq[col][2]
end
local result = { '"' .. table.concat( x, '","' ) .. '"' }
for _, row in ipairs( cQuery ) do
x = {}
for i, col in ipairs( columns ) do
x[i] = dQ( row[col] or '' )
end
result[#result+1] = '"' .. table.concat( x, '","' ) .. '"'
end
return table.concat( result, '\n' )
end
function p.Collect( frame )
local fn = mw.text.trim( frame:getParent().args[1] or '' )
local base = mw.title.getCurrentTitle().baseText
if fn == '-:' then
fn = mw.ustring.gsub( base, ':[^:]+$', '' )
end
local subp = mw.title.getCurrentTitle().subpageText
if fn == '' then
fn = base
end
return frame:callParserFunction( '#a2f', 'Избирательные кампании/Объекты/Данные kml/pattern', fn, fn .. '.kml' )
.. frame:callParserFunction( '#a2f', 'Избирательные кампании/Объекты/Данные gpx/pattern', fn, fn .. '.gpx' )
.. frame:callParserFunction( '#a2f', 'Избирательные кампании/Объекты/Данные json/pattern', fn, fn .. '.json' )
.. frame:callParserFunction( '#a2f', 'Избирательные кампании/Объекты/Данные csv/pattern', mw.title.getCurrentTitle().text, base .. ' - ' .. subp .. '.csv' )
end
return p