Модуль:Index: различия между версиями
Материал из Указатель частей и соединений РККА 1941-1945
Строк (обсуждение | вклад) |
Строк (обсуждение | вклад) |
||
Строка 23: | Строка 23: | ||
['без вики-категории'] = 'нет', | ['без вики-категории'] = 'нет', | ||
} ) | } ) | ||
− | local cats = mw.text.split( args['категории'], ' *[,\n] *' ) | + | local cats = mw.text.split( args['категории'], ' *[,\n]+ *' ) |
local request = {} | local request = {} | ||
if #cats == 1 and mw.ustring.sub( cats[1], 1, 4 ) == 'гв. ' then -- ради страниц категорий гв. минометов | if #cats == 1 and mw.ustring.sub( cats[1], 1, 4 ) == 'гв. ' then -- ради страниц категорий гв. минометов |
Версия 13:05, 24 марта 2020
Для документации этого модуля может быть создана страница Модуль:Index/doc
local p = {} local global = mw.ext.luaglobal local tools = require( 'Module:Tools' ) local cargo = mw.ext.cargo --[[ старт: Запрос к БД, вытаскиваем всё в глобал печать: - заголовок таблицы - сотня (диапазон номеров и как формируется — сплошным перебором или существующими номерами в указанном диапазоне проблемы: 101 номер, 90 почти подряд и 5 вразбивку) описывать отдельно каждую сотню мешает то, что их может быть неопределенно много варианты описания: 0-599/200 = все подряд по 200 штук, *300-5999/100 — существующие в указанном диапазоне сложные сотни? 0-49 подряд, потом разбивка --]] function p.Query( frame ) local args = tools.checkargs( frame:getParent().args, { ['категории'] = '', ['номера'] = '', ['гвардия'] = '*', ['отд.'] = '*', ['без вики-категории'] = 'нет', } ) local cats = mw.text.split( args['категории'], ' *[,\n]+ *' ) local request = {} if #cats == 1 and mw.ustring.sub( cats[1], 1, 4 ) == 'гв. ' then -- ради страниц категорий гв. минометов -- cats[1] = mw.ustring.sub( cats[1], 5, -1 ) args['гвардия'] = 'да' end for _, cat in ipairs( cats ) do if cat ~= '' then table.insert( request, 'class="' .. cat ..'"' ) end end if #request == 0 then error( 'Не заданы категории для запроса' ) end local noctg = require( 'Module:Yesno') ( args['без вики-категории'], true ) request = '(' .. table.concat( request, ' OR ' ) .. ')' local guards = require( 'Module:Yesno') ( args['гвардия'], '*' ) if guards ~= '*' then if guards then request = request .. ' AND guard=TRUE' else request = request .. ' AND guard IS NULL' end end local standalone = require( 'Module:Yesno') ( args['отд.'], '*' ) if standalone ~= '*' then if standalone then request = request .. ' AND standalone=TRUE' else request = request .. ' AND standalone IS NULL' end end local qq = cargo.query( 'unitpages', 'unit, class, first, last, special, number', { where = request, -- .. ' AND (special is NULL OR special <> "a")', orderBy = 'number, class, special, unit', limit = 5000, } ) if #qq == 0 then return '<p>Запрос вернул пустой результат.</p>' end local res = {} if not noctg then table.insert( res, '[[Category:' .. table.concat( cats, '|*]][[Category:' ) .. '|*]]' ) end local blocksArray = args['номера'] if blocksArray == 'текст' or blocksArray == 'текст+' then table.sort( qq, function ( a, b ) local an, at = string.match( a.unit, '^(%d*) *(.+)$' ) local bn, bt = string.match( b.unit, '^(%d*) *(.+)$' ) if at < bt then return true elseif at == bt then return ('0'..an) < ('0'..bn) else return false end end ) local common = ' ' .. cats[1] if blocksArray == 'текст+' then common = '!!!' end local lcommon = - #common for _, u in ipairs( qq ) do local txt = u.unit if string.sub( txt, lcommon, -1 ) == common then txt = string.sub( txt, 1, lcommon-1 ) end table.insert( res, '<div class=idx-button-text>' .. '[[' .. u.unit .. '|<span style=color:black>'.. txt .. '</span>]]</div>' ) end return table.concat( res ) end -- это всё фиктивный кусок, потому что блок всегда один blocksArray = mw.text.split( blocksArray, '%s*;%s*' ) local currentBlock = 0 local block local function newBlock() currentBlock = currentBlock + 1 if blocksArray[currentBlock] then local arr = mw.text.split( blocksArray[currentBlock], '%s*,%s*' ) block = {} for _, u in ipairs( arr ) do local x, y, z if tonumber( u ) then x, y, z = '', u, u else x, y, z = string.match( u, '^(%*?)(%d+)%-(%d+)$' ) if not x then error( 'Кривой диапазон' ) end end y, z = tonumber( y ), tonumber( z ) if y > z then error( 'Кривой диапазон' ) end table.insert( block, { tonumber( y ), tonumber( z ), x ~= '*' } ) end return block end end newBlock() table.insert( block, 1, { -3, -1, false } ) table.insert( block, {99998, 99999, false } ) local currentDiap = 1 local delta = 0 local outres = { } local minnum = 999999 local maxnum = -1 local function toPrint( unit, number ) if number > maxnum then maxnum = number end if number < minnum then minnum = number end if outres[number] then table.insert( outres[number], unit ) else outres[number] = { unit } end end -- do return mw.dumpObject( block ) end for _, unit in ipairs( qq ) do -- если предыдущий блок должен был завершиться, то он уже завершен -- (блок завершается либо по фиксированному числу элементов (но продлевается, -- если осталось 20 или менее элементов), либо по «;» в списке номеров) -- -- пока блоки не трогаем, считаем, что блок единственный. -- текущим элементом раскладки является диапазон block[currentDiap] со сдвигом delta от начала. -- это означает, что в эту позицию мы уже что-то выводили -- если текущий unit имеет номер меньше текущей раскладки, то мы «аварийно» его выводим local num = unit.number if num == '' then num = 0 else num = tonumber( num ) end if num < block[currentDiap][1] + delta then unit.warning = 'regular' --'over' toPrint( unit, num ) elseif num == block[currentDiap][1] + delta then toPrint( unit, num ) else for diap = currentDiap, #block do if num <= block[diap][2] then if diap ~= currentDiap then delta = 0 else delta = delta+1 end currentDiap = diap break end if block[diap][3] then local start if diap == currentDiap then start = delta + 1 else start = 0 end for i = block[diap][1] + start, block[diap][2] do toPrint( { warning = 'empty' }, i ) end end end -- мы в нужном блоке if block[currentDiap][3] then for i = block[currentDiap][1]+delta, num - 1 do toPrint( { warning = 'empty' }, i ) end end delta = num - block[currentDiap][1] toPrint( unit, num ) end end -- do return mw.dumpObject( outres ) end for i = minnum, maxnum do local units = outres[i] local txt = i if i == 0 then txt = '<span style="letter-spacing:-0.3ex; font-style:italic;"> <sup>б</sup>/<sub>№</sub></span>' end if units then if #units == 1 and ( i ~= 0 or units[1].warning == 'empty' )then if units[1].warning == 'empty' then table.insert( res , '<div class=idx-button-empty>' .. '<span style="font-size:120%; margin:0">' .. txt .. '</span>' .. '</div>' ) else table.insert( res , '<div class=idx-button-' .. ( units[1].warning or 'regular' ) .. '>' .. '<span style="font-size:120%; margin:0">[[' .. units[1].unit .. '|<span style=color:black>'.. txt .. '</span>]]</span>' .. '</div>' ) end else table.insert( res , '<div class=dropdown style=display:inline-block>' .. '<div class="idx-button-' .. ( units[1].warning or 'regular' ) .. ' dropdown-toggle" data-toggle="dropdown">' .. '<span style="font-size:120%; margin:0">'.. txt .. '<br><i class="fa fa-caret-down"></i></span>' .. '</div><div class="dropdown-menu idx-dropdown">' ) local unitsA = {} for _, u in ipairs( units ) do local pre, post = '', '' if u.special == 'a' then pre = '<i>' post = '</i> <i class="fa fa-mail-forward" title="Альтернативное наименование"></i>' elseif u.special == 'm' then pre = '<i>' post = '</i> <i class="fa fa-random" title="Разрешение неоднозначного наименования"></i>' end table.insert( unitsA, '<p>' .. pre .. '[[' .. u.unit .. ']]' .. post .. '</p>' ) end table.insert( res, table.concat( unitsA ) ) table.insert( res, '</div></div>' ) end end end return table.concat( res ) end return p