Модуль:Page — различия между версиями

Материал из Указатель частей и соединений РККА 1941-1945
Перейти к:навигация, поиск
 
Строка 178: Строка 178:
 
table.insert( res, '<span class="' .. collapsed
 
table.insert( res, '<span class="' .. collapsed
 
.. '"><span class=bracket-' .. ( chain.double or 'none' ) .. '>&nbsp;</span><b>'
 
.. '"><span class=bracket-' .. ( chain.double or 'none' ) .. '>&nbsp;</span><b>'
.. report.printDateLink( chain.page, chain.bookpage )
+
.. report.printDateWithLink( chain )
 
.. '</b> &nbsp; ' .. chain.print .. '<br></span>' )
 
.. '</b> &nbsp; ' .. chain.print .. '<br></span>' )
 
if chain.controller then
 
if chain.controller then
Строка 280: Строка 280:
 
local child = el[2]
 
local child = el[2]
 
if newdate then
 
if newdate then
table.insert( res, hr .. '<p><b>' .. report.printDateLink( child.page, child.bookpage ) .. '</b> &nbsp; ' )
+
table.insert( res, hr .. '<p><b>' .. report.printDateWithLink( child ) .. '</b> &nbsp; ' )
 
newdate = nil
 
newdate = nil
 
comma = nil
 
comma = nil
Строка 953: Строка 953:
 
global.set( 'PageIsNotEmpty', true )
 
global.set( 'PageIsNotEmpty', true )
 
end
 
end
+
 
 
local linksout = require( 'Module:LinksOut' )
 
local linksout = require( 'Module:LinksOut' )
 
local links = linksout.collect( enumunits )
 
local links = linksout.collect( enumunits )
Строка 961: Строка 961:
 
global.set( 'PageIsNotEmpty', true )
 
global.set( 'PageIsNotEmpty', true )
 
end
 
end
+
 
 
if not global.get( 'PageIsNotEmpty' ) then
 
if not global.get( 'PageIsNotEmpty' ) then
 
table.insert( out, '[[Категория:Пустая страница формирования]]' )
 
table.insert( out, '[[Категория:Пустая страница формирования]]' )

Текущая версия на 20:06, 21 мая 2020

Для документации этого модуля может быть создана страница Модуль:Page/doc

local p = {}
local global = mw.ext.luaglobal
local cargo = mw.ext.cargo
local ref = require( 'Module:Ref' )
local report = require( 'Module:Report' )
local tools = require( 'Module:Tools' )
local cat = require( 'Module:Categories' ) -- loadData не позволяет пользоваться #...  и т. п.
local lexer = require( 'Module:Lexer' )
local dataOut = mw.loadData( 'Module:DataOut' )
local first, last

local DIVIDER = ',&nbsp; '

local dateset = {
	['1941-06-22'] = {  1,   1, },
	['1941-07-01'] = {  2,   1, },
	['1941-07-10'] = {  3,   1, },
	['1941-08-01'] = {  4,   2, },
	['1941-09-01'] = {  5,   3, },
	['1941-10-01'] = {  6,   4, },
	['1941-11-01'] = {  7,   5, },
	['1941-12-01'] = {  8,   6, },
	['1942-01-01'] = {  9,   7, },
	['1942-02-01'] = { 10,   8, },
	['1942-03-01'] = { 11,   9, },
	['1942-04-01'] = { 12,  10, },
	['1942-05-01'] = { 13,  11, },
	['1942-06-01'] = { 14,  12, },
	['1942-07-01'] = { 15,  13, },
	['1942-08-01'] = { 16,  14, },
	['1942-09-01'] = { 17,  15, },
	['1942-10-01'] = { 18,  16, },
	['1942-11-01'] = { 19,  17, },
	['1942-12-01'] = { 20,  18, },
	['1943-01-01'] = { 21,  19, },
	['1943-02-01'] = { 22,  20, },
	['1943-03-01'] = { 23,  21, },
	['1943-04-01'] = { 24,  22, },
	['1943-05-01'] = { 25,  23, },
	['1943-06-01'] = { 26,  24, },
	['1943-07-01'] = { 27,  25, },
	['1943-08-01'] = { 28,  26, },
	['1943-09-01'] = { 29,  27, },
	['1943-10-01'] = { 30,  28, },
	['1943-11-01'] = { 31,  29, },
	['1943-12-01'] = { 32,  30, },
	['1944-01-01'] = { 33,  31, },
	['1944-02-01'] = { 34,  32, },
	['1944-03-01'] = { 35,  33, },
	['1944-04-01'] = { 36,  34, },
	['1944-05-01'] = { 37,  35, },
	['1944-06-01'] = { 38,  36, },
	['1944-07-01'] = { 39,  37, },
	['1944-08-01'] = { 40,  38, },
	['1944-09-01'] = { 41,  39, },
	['1944-10-01'] = { 42,  40, },
	['1944-11-01'] = { 43,  41, },
	['1944-12-01'] = { 44,  42, },
	['1945-01-01'] = { 45,  43, },
	['1945-02-01'] = { 46,  44, },
	['1945-03-01'] = { 47,  45, },
	['1945-04-01'] = { 48,  46, },
	['1945-05-01'] = { 49,  47, },
	['1945-06-01'] = { 50,  48, },
	['1945-07-01'] = { 51,  48, },
	['1945-08-01'] = { 52,  49, },
	['1945-08-09'] = { 53,  49, },
	['1945-09-03'] = { 54,  50, },
}

function p.parents( unit )

	unit = '(' .. unit .. ') AND t0.fixparent <> "структура"'
	local parents = cargo.query(
		'units=t0, units=t1, units=t2, units=t3, units=t4, units=t5, units=t6, '
			.. 'units=t0s, units=t1s, units=t2s, units=t3s, units=t4s, units=t5s, units=t6s',
		't0.fix=date, t0.war=war, t0.fixunit=porno, '
			.. 't0.unit=id0, t0.addendum=add0, t0.ref=ref0, t0.creating=form0, t0.ass=ass0, t0.tab=tab0, t0.hq=hq0, t0s.unit=s_id0, t0s.addendum=s_add0, t0s.ref=s_ref0, '
			.. 't1.unit=id1, t1.addendum=add1, t1.ref=ref1, t1.creating=form1, t1.ass=ass1, t1.tab=tab1, t1.hq=hq1, t1s.unit=s_id1, t1s.addendum=s_add1, t1s.ref=s_ref1, '
			.. 't2.unit=id2, t2.addendum=add2, t2.ref=ref2, t2.creating=form2, t2.ass=ass2, t2.tab=tab2, t2.hq=hq2, t2s.unit=s_id2, t2s.addendum=s_add2, t2s.ref=s_ref2, '
			.. 't3.unit=id3, t3.addendum=add3, t3.ref=ref3, t3.creating=form3, t3.ass=ass3, t3.tab=tab3, t3.hq=hq3, t3s.unit=s_id3, t3s.addendum=s_add3, t3s.ref=s_ref3, '
			.. 't4.unit=id4, t4.addendum=add4, t4.ref=ref4, t4.creating=form4, t4.ass=ass4, t4.tab=tab4, t4.hq=hq4, t4s.unit=s_id4, t4s.addendum=s_add4, t4s.ref=s_ref4, '
			.. 't5.unit=id5, t5.addendum=add5, t5.ref=ref5, t5.creating=form5, t5.ass=ass5, t5.tab=tab5, t5.hq=hq5, t5s.unit=s_id5, t5s.addendum=s_add5, t5s.ref=s_ref5, '
			.. 't6.unit=id6, t6.addendum=add6, t6.ref=ref6, t6.creating=form6, t6.ass=ass6, t6.tab=tab6, t6.hq=hq6, t6s.unit=s_id6, t6s.addendum=s_add6, t6s.ref=s_ref6, '
			.. 't0._pageName=page, t0.page=bookpage',
		{
			join    =  't0.fixparent=t1.fixunit, t0.fixstruct=t0s.fixunit, '
					.. 't1.fixparent=t2.fixunit, t1.fixstruct=t1s.fixunit, '
					.. 't2.fixparent=t3.fixunit, t2.fixstruct=t2s.fixunit, '
					.. 't3.fixparent=t4.fixunit, t3.fixstruct=t3s.fixunit, '
					.. 't4.fixparent=t5.fixunit, t4.fixstruct=t4s.fixunit, '
					.. 't5.fixparent=t6.fixunit, t5.fixstruct=t5s.fixunit, '
					.. 't6.fixstruct=t6s.fixunit ',
			where   = unit,
			orderBy = 'date, porno', -- по порно, чтобы дубликаты в одинаковой последовательности шли
		} )

	local res = {}
	local timelineClass = {}
	if #parents ~= 0 then
		first = parents[1].date
		last = parents[#parents].date
	else
--		first = '1941-01-01'
--		last = '1945-12-31'
		return
	end

	local prev

	for _, chain in ipairs( parents ) do
		local str = {}
		for i = 0, 6 do
			local x = report.outEl( chain, i, 2, i ~= 0 )
			if x then
				table.insert( str, x )
			else
				break
			end
		end
		chain.print = table.concat( str, ' / ' )
		if prev then
			if chain.date == prev.date then
				if not prev.double then
					prev.double = 'start'
				end
				chain.double = 'middle'
				-- здесь еще надо добавить разборку с последовательностью
			else
				if prev.double then
					prev.double = 'stop'
				end
				if prev then
					if dateset[chain.date][1]-dateset[prev.date][1] ~= 1 then
						chain.hrbefore = true
					end
				end
			end
		end
		timelineClass[dateset[chain.date][2]] = chain.war
		prev = chain
	end
	if prev.double then
		prev.double = 'stop'
	end



	local linum = 0
	while linum < #parents do
		linum = linum+1
		local line = parents[linum]
		if not line.double then
			local counter = 0
			for i = linum+1, #parents do
				local linext = parents[i]
				if linext.double or linext.hrbefore or linext.print ~= line.print then
					break
				end
				linext.control = linum
				counter = counter+1
			end
			if counter > 2 then
				line.controller = true
				parents[linum+counter].control = nil -- последний не управляется
			end
			linum = linum + counter
		end
	end
	for number, chain in ipairs( parents ) do
		if chain.hrbefore then
			table.insert( res, '<hr style="margin:5px;">' )
		end
		local collapsed = ''
		if chain.control and parents[chain.control].controller then
			collapsed ='collapse parents-control-' .. chain.control
		end
		table.insert( res, '<span class="' .. collapsed
			.. '"><span class=bracket-' .. ( chain.double or 'none' ) .. '>&nbsp;</span><b>'
			.. report.printDateWithLink( chain )
			.. '</b> &nbsp; ' .. chain.print .. '<br></span>' )
		if chain.controller then
			table.insert( res, '<span class="collapse in parents-control-'
				.. number .. '" data-toggle="collapse" data-target=".parents-control-'
				.. number .. '"><b><span class=bracket-none>&nbsp;</span>'
				.. '<span class="date-field text-muted">&middot;&nbsp; &middot;&nbsp; &middot;&nbsp; &middot;&nbsp; &middot;</span></b>'
				.. ' &nbsp; <span class="small text-muted"><i>&nbsp; &nbsp;Сведения повторяются на все промежуточные даты. [[#0|Показать?]]</i></span><br></span>' )
		end
	end

	local timeline = {}
	for i = 1, 50 do
		table.insert( timeline, '<hr class="timeline tl-' .. ( timelineClass[i] or 'n' ) .. '">' )
	end

	return table.concat( res ), table.concat( timeline )
end

function p.children( unit, father, tab, dateS, dateF )
	if tab then
		unit = '(' .. unit .. ')'
			.. ' AND (t1.tab IS NULL OR t1.tab="' .. tab .. '")'
			.. ' AND (t2.tab IS NULL OR t2.tab="' .. tab .. '")'
			.. ' AND (t3.tab IS NULL OR t3.tab="' .. tab .. '")'
			.. ' AND (t4.tab IS NULL OR t4.tab="' .. tab .. '")'
			.. ' AND (t5.tab IS NULL OR t5.tab="' .. tab .. '")'
			.. ' AND (t6.tab IS NULL OR t6.tab="' .. tab .. '")'
	end
	if dateS then
		unit = '(' .. unit .. ') AND (t0.fix BETWEEN "' .. dateS .. '" AND "' .. dateF .. '")'
	end
	local query_tables =
		'units=t0, units=t1, units=t2, units=t3, units=t4, units=t5, units=t6, '
			.. --[['units=t0s,]] 'units=t1s, units=t2s, units=t3s, units=t4s, units=t5s, units=t6s'
	local query_fields =
		't0.fix=date, t0.war=war, '
			.. 't0.unit=id0, t0.addendum=add0, t0.ref=ref0, t0.creating=form0, t0.ass=ass0, t0.tab=tab0, t0.hq=hq0, t0.fixunit=porno0,  ' -- t0s.unit=s_id0, t0s.addendum=s_add0, t0s.ref=s_ref0, '
			.. 't1.unit=id1, t1.addendum=add1, t1.ref=ref1, t1.creating=form1, t1.ass=ass1, t1.tab=tab1, t1.hq=hq1, t1.fixunit=porno1,  t1s.unit=s_id1, t1s.addendum=s_add1, t1s.ref=s_ref1, '
			.. 't2.unit=id2, t2.addendum=add2, t2.ref=ref2, t2.creating=form2, t2.ass=ass2, t2.tab=tab2, t2.hq=hq2, t2.fixunit=porno2,  t2s.unit=s_id2, t2s.addendum=s_add2, t2s.ref=s_ref2, '
			.. 't3.unit=id3, t3.addendum=add3, t3.ref=ref3, t3.creating=form3, t3.ass=ass3, t3.tab=tab3, t3.hq=hq3, t3.fixunit=porno3,  t3s.unit=s_id3, t3s.addendum=s_add3, t3s.ref=s_ref3, '
			.. 't4.unit=id4, t4.addendum=add4, t4.ref=ref4, t4.creating=form4, t4.ass=ass4, t4.tab=tab4, t4.hq=hq4, t4.fixunit=porno4,  t4s.unit=s_id4, t4s.addendum=s_add4, t4s.ref=s_ref4, '
			.. 't5.unit=id5, t5.addendum=add5, t5.ref=ref5, t5.creating=form5, t5.ass=ass5, t5.tab=tab5, t5.hq=hq5, t5.fixunit=porno5,  t5s.unit=s_id5, t5s.addendum=s_add5, t5s.ref=s_ref5, '
			.. 't6.unit=id6, t6.addendum=add6, t6.ref=ref6, t6.creating=form6, t6.ass=ass6, t6.tab=tab6, t6.hq=hq6, t6.fixunit=porno6,  t6s.unit=s_id6, t6s.addendum=s_add6, t6s.ref=s_ref6, '
			.. 't0._pageName=page, t0.page=bookpage'
	local query_args = {
			join    =  't0.fixunit=t1.fixparent, ' -- t0.fixstruct=t0s.fixunit, '
					.. 't1.fixunit=t2.fixparent, t1.fixstruct=t1s.fixunit, '
					.. 't2.fixunit=t3.fixparent, t2.fixstruct=t2s.fixunit, '
					.. 't3.fixunit=t4.fixparent, t3.fixstruct=t3s.fixunit, '
					.. 't4.fixunit=t5.fixparent, t4.fixstruct=t4s.fixunit, '
					.. 't5.fixunit=t6.fixparent, t5.fixstruct=t5s.fixunit, '
					.. 't6.fixstruct=t6s.fixunit ',
			where   = unit,
			orderBy = 'date, porno1, porno2, porno3, porno4, porno5, porno6',
			limit   = 5000,
		}

	local children = cargo.query( query_tables, query_fields, query_args )
	if #children == 5000 then
		query_args.offset = 5000
--		query_args.limit = 5000
		local children1 = cargo.query( query_tables, query_fields, query_args )
		for _, ch in ipairs( children1 ) do
			table.insert( children, ch )
		end
	elseif not next( children ) then
		return
	end

--[[
Количество закрывающих скобок равно количеству отличающихся концевых элементов предыдущего минус 1
За всеми новыми элементами, кроме последнего, следует открывающая скобка
--]]
	local pageGene
	local x = string.match( father, '^[^(]+ %(([^()]+)%)' )
	if type( report.knownBrackets[x] ) == 'string' then
		pageGene = x
	end

	local tt = require( 'Module:Traversal' )
	tt.init( children, father )


	local gene = { pageGene }
	local lastdate
	local newdate -- в момент получения элемента нам неизвестна страница, она возникнет только при первом элементе. Поэтому мы ее запоминаем, а при получении элемента проверяем на nil
	local res = { '<div class=bs-children>' }
	local flat = {}
	local hr = ''
	local comma

	while true do
		local el = tt.get()
		if not el then
--			table.insert( res, table.concat( pack ) )
			break
		end
		local elt = el[1]
		if type( elt ) == 'number' then
			local child = el[2]
			if newdate then
				table.insert( res, hr .. '<p><b>' .. report.printDateWithLink( child ) .. '</b> &nbsp; ' )
				newdate = nil
				comma = nil
			end
			if not el[3] then
				report.gene = gene[#gene]
				table.insert( flat, report.outEl( child, elt, 1, true, true ) ) -- кратко, ссылки, упаковка
			else
				table.insert( flat, report.popBuffer() )
				if next( flat ) then
					if comma then
						table.insert( res, DIVIDER )
					end
					table.insert( res, table.concat( flat, DIVIDER ) )
					flat  = {}
					comma = true
				end
				local tagO, tagC = '', ''
				if child['ass'..elt] ~= '' then
					tagO = '<b>'
					tagC = '</b>'
				else
					tagO = '<u>'
					tagC = '</u>'
				end
				if comma then
					table.insert( res, DIVIDER )
				end
				report.gene = gene[#gene]
				table.insert( res, '<span class=childs>' .. tagO .. report.outEl( child, elt, 1, true ) .. tagC .. ' (' )
				table.insert( gene, report.gene )
				comma = nil
			end
		elseif elt == '(' then
			-- skip все сделали на элементе
		elseif elt == ')' then
			table.insert( flat, report.popBuffer() )
			if next( flat ) then
				if comma then
					table.insert( res, DIVIDER )
				end
				table.insert( res, table.concat( flat, DIVIDER ) )
				flat  = {}
			end
			table.remove( gene )
			table.insert( res, ')</span>' )
			comma = true
		elseif elt == '|' then
			table.insert( flat, report.popBuffer() )
			if next( flat ) then
				if comma then
					table.insert( res, DIVIDER )
				end
				table.insert( res, table.concat( flat, DIVIDER ))
				flat  = {}
			end
			comma = nil
			table.insert(res, ' &nbsp;<b>||</b>&nbsp; ' )
		elseif elt == '{' then
			if ( lastdate and dateset[el[2]][1]-dateset[lastdate][1] ~= 1 ) or newdate then
				hr = '<hr style="margin:5px;">'
			else
				hr = ''
			end
			newdate = true
			lastdate = el[2]
		elseif elt == '}' then
			table.insert( flat, report.popBuffer() )
			if next( flat ) then
				if comma then
					table.insert( res, DIVIDER )
				end
				table.insert( res, table.concat( flat, DIVIDER ))
				flat  = {}
			end
			if not newdate then
--				table.insert( res, ' &nbsp; [' .. tostring( mw.uri.fullUrl( father, 'more=' .. lastdate ) )
				table.insert( res, ' &nbsp; [' .. mw.site.server .. '/oob/' .. lastdate .. '/' .. string.gsub( father, ' ', '_' )
					.. ' <i class="fa fa-search-plus" title="Показать развернутый список без сокращений"></i>]</p>' )
			end
		end
	end
	table.insert( res, '</div>' )
	if #children >= 9999 then
		table.insert( res, '<p class=error>Сведения о составе чересчур объемны (' .. #children .. ')! Выдача прервана.</p>' )
	end

	if #res ~= 2 then
		return table.concat( res )
	end
end

function p.separate( unit )
--	if type( unit ) == 'string' then
--		unit = 't0.unit="' .. unit .. '"'
--	else
--		unit = 't0.unit="' .. table.concat( unit, '" OR t0.unit="' ) .. '"'
--	end
	local separate = cargo.query(
		'units=t0, units=t1, units=t2, units=t3, units=t4, units=t5, units=t6, '
			.. 'units=t0s, units=t1s, units=t2s, units=t3s, units=t4s, units=t5s, units=t6s',
		't0.fix=date, t0.war=war, '
			.. 't0.unit=id0, t0.addendum=add0, t0.ref=ref0, t0.creating=form0, t0.ass=ass0, t0.tab=tab0,  t0s.unit=s_id0, t0s.addendum=s_add0, t0s.ref=s_ref0, '
			.. 't1.unit=id1, t1.addendum=add1, t1.ref=ref1, t1.creating=form1, t1.ass=ass1, t1.tab=tab1,  t1s.unit=s_id1, t1s.addendum=s_add1, t1s.ref=s_ref1, '
			.. 't2.unit=id2, t2.addendum=add2, t2.ref=ref2, t2.creating=form2, t2.ass=ass2, t2.tab=tab2,  t2s.unit=s_id2, t2s.addendum=s_add2, t2s.ref=s_ref2, '
			.. 't3.unit=id3, t3.addendum=add3, t3.ref=ref3, t3.creating=form3, t3.ass=ass3, t3.tab=tab3,  t3s.unit=s_id3, t3s.addendum=s_add3, t3s.ref=s_ref3, '
			.. 't4.unit=id4, t4.addendum=add4, t4.ref=ref4, t4.creating=form4, t4.ass=ass4, t4.tab=tab4,  t4s.unit=s_id4, t4s.addendum=s_add4, t4s.ref=s_ref4, '
			.. 't5.unit=id5, t5.addendum=add5, t5.ref=ref5, t5.creating=form5, t5.ass=ass5, t5.tab=tab5,  t5s.unit=s_id5, t5s.addendum=s_add5, t5s.ref=s_ref5, '
			.. 't6.unit=id6, t6.addendum=add6, t6.ref=ref6, t6.creating=form6, t6.ass=ass6, t6.tab=tab6,  t6s.unit=s_id6, t6s.addendum=s_add6, t6s.ref=s_ref6, '
			.. 't0._pageName=page',
		{
--			join    = 't0.fixunit=t1.fixstruct, t1.fixparent=t2.fixunit, t2.fixparent=t3.fixunit, t3.fixparent=t4.fixunit, t4.fixparent=t5.fixunit, t5.fixparent=t6.fixunit',
			join    =  't0.fixunit=t1.fixstruct, t0.fixstruct=t0s.fixunit, '
					.. 't1.fixparent=t2.fixunit, t1.fixstruct=t1s.fixunit, '
					.. 't2.fixparent=t3.fixunit, t2.fixstruct=t2s.fixunit, '
					.. 't3.fixparent=t4.fixunit, t3.fixstruct=t3s.fixunit, '
					.. 't4.fixparent=t5.fixunit, t4.fixstruct=t4s.fixunit, '
					.. 't5.fixparent=t6.fixunit, t5.fixstruct=t5s.fixunit, '
					.. 't6.fixstruct=t6s.fixunit ',

			where   = unit,
			orderBy = 'date',
		} )
	local res = {}
	local lastdate
	for _, child in ipairs( separate ) do
		if child.id1 ~= '' then
			local x
			if child.date ~= lastdate then
				x = child.date
				lastdate = x
			end
			child.s_id1 = '' -- не надо тут структурного отца
			local str = {}
			for i = 1, 6 do
				local x = report.outEl( child, i, 2, true )
				if x then
					table.insert( str, x )
				else
					break
				end
			end
			str = '<b>' .. report.printDate( x ) .. '</b> &nbsp; ' .. table.concat( str, ' / ' )
			table.insert( res, str )
		end
	end
	if #res ~= 0 then
		return table.concat( res, '<br>' )
	end
end
--[===[
local function makeWhere( units, field )
	field = field or 't0.unit'
	return '(' .. field .. '="' .. table.concat( units, '" OR ' .. field .. '="' ) .. '")'
end

local function todate( str, last )
	local p = mw.text.split( str, '.', true )
	assert( #p <= 3 )
	local d, m, y
	y = tonumber( p[#p] )
	if #p ~= 1 then
		m = tonumber( p[#p-1] )
	end
	if #p == 3 then
		d = tonumber( p[1] )
	end
	if y < 1900 then
		y = y + 1900
	end
	if not m then
		if last then
			m = 12
		else
			m = 1
		end
	end
	if not d then
		if last then
			if m == 2 and y % 4 == 0 then
				d = 29
			else
				d = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
				d = d[m]
			end
		else
			d = 1
		end
	end
	return y .. '-' .. string.sub( '0' .. m , -2, -1 ) .. '-' .. string.sub( '0' .. d , -2, -1 )
end
--]===]
local function parseClauses( str )
	if str == '' then
		return nil
	end
	local clauses = mw.text.split( str, '$', true )
	local resA = {}
	for _, clause in ipairs( clauses ) do
		local clauseParts = mw.text.split( clause, ';' )
		assert( #clauseParts == 4, 'Не 4, а ' ..  #clauseParts )
		local tops, topsDirectly = clauseParts[3], clauseParts[4]
		if tops == '' then
			tops = nil
		else
			tops = mw.text.split( clauseParts[3], ',' )
		end
		if topsDirectly == '' then
			topsDirectly = nil
		else
			topsDirectly = mw.text.split( clauseParts[4], ',' )
		end
		table.insert( resA, {
				from = clauseParts[1],
				to = clauseParts[2],
				tops = tops,
				topsDirectly = topsDirectly,
			} )
	end
	return resA
end


local function collectRedirect( target )
	local query = cargo.query( 'redirects', '_pageName, selector',
		{ where = 'redirectname="' .. target .. '"', } )
	local descriptors = {}
	for _, row in ipairs( query ) do
		local clauses = mw.text.split( row.selector, '#' )
		assert( #clauses == 2 )
		table.insert( descriptors, {
				unit = row._pageName,
				inc = parseClauses( clauses[1] ),
				exc = parseClauses( clauses[2] ),
			} )
	end
	return descriptors
end


local function sqlIncExc( clauses )
	local res = {}
	for _,clause in ipairs( clauses ) do
		local elem = { }
		local x
		if clause.from ~= '' and clause.to ~= '' then
			x = 't0.fix BETWEEN "' .. clause.from .. '" AND "' .. clause.to .. '"'
		elseif clause.from ~= '' then
			x = 't0.fix >= "' .. clause.from .. '"'
		elseif clause.to ~= '' then
			x = 't0.fix <= "' .. clause.to .. '"'
		end
		table.insert( elem, x )
		x = {}
		if clause.topsDirectly and #clause.topsDirectly ~= 0 then
			local z = ' IN ("' .. table.concat( clause.topsDirectly, '", "' ) .. '")'
			table.insert( x, 't0.parent' .. z  )
		end
		if clause.tops and #clause.tops ~= 0 then
--			local z = ' IN ("' .. table.concat( clause.tops, '", "' ) .. '")'
--			table.insert( x, 't0.parent' .. z .. ' OR '
--				.. 't1.parent' .. z .. ' OR '
--				.. 't2.parent' .. z .. ' OR '
--				.. 't3.parent' .. z .. ' OR '
--				.. 't4.parent' .. z .. ' OR '
--				.. 't5.parent' .. z )
			table.insert( x, 't0.parent="' .. table.concat( clause.tops, '" OR t0.parent="' ) .. '" OR '
				.. 't1.parent IS NOT NULL AND t1.parent IN ("' .. table.concat( clause.tops, '", "' ) .. '") OR '
				.. 't2.parent IS NOT NULL AND t2.parent IN ("' .. table.concat( clause.tops, '", "' ) .. '") OR '
				.. 't3.parent IS NOT NULL AND t3.parent IN ("' .. table.concat( clause.tops, '", "' ) .. '") OR '
				.. 't4.parent IS NOT NULL AND t4.parent IN ("' .. table.concat( clause.tops, '", "' ) .. '") OR '
				.. 't5.parent IS NOT NULL AND t5.parent IN ("' .. table.concat( clause.tops, '", "' ) .. '")' )
		end
		if next( x ) then
			table.insert( elem, table.concat( x, ' OR ' ) )
		end
		if next( elem ) then
			table.insert( res, '(' .. table.concat( elem, ') AND (' ) .. ')' )
		else
			table.insert( res, '0=0')
		end
	end
	return table.concat( res, ' OR ' )
end

--[=[
local function disambigCheck()
-- проверяет существование страниц неоднозначностей на основании имени страницы
-- возвращает имя страницы и текст предупреждения
	local pageTitleText = mw.title.getCurrentTitle().text
	local tmp = string.find( pageTitleText, ' (', 1, true )
	local cleanTitle
	if tmp then
		cleanTitle = string.sub( pageTitleText, 1, tmp-1 )
		tmp = '(unit="' .. cleanTitle .. '" OR unit="' .. cleanTitle .. ' (*)")'
	else
		cleanTitle = pageTitleText
		tmp = 'unit="' .. pageTitleText .. ' (*)"'
	end
	local sameName = cargo.query( 'unitpages', 'unit,special', {
			where = tmp .. ' AND special="d"' } )
	assert( #sameName <= 1 )
	if #sameName == 1 then
		return pageTitleText, '<p class=disambig-warning>Имеются другие формирования с наименованием «'
			.. cleanTitle .. '» (см. [[' .. sameName[1].unit .. '|список]]).</p>'
	end
	return pageTitleText
end
--]=]

function p._unit( args, frame, mode, part )

	local out = {}

--	local pageTitleText, tmp = disambigCheck()
--	table.insert( out, tmp )

	local pageTitleText = mw.title.getCurrentTitle().text

	local baseName, braces = string.match( pageTitleText, '^([^(]+) %((.+)%)$' )
	local generation, disambig, foreigner = '', '', ''
	baseName = baseName or pageTitleText
	if braces then
		local bracesArr = mw.text.split( braces, ') (', true )
		for _, brace in ipairs( bracesArr ) do
			if dataOut.generation[brace] then
				generation = ' <i>' .. dataOut.generation[brace] .. ' формирование</i>'
			elseif dataOut.foreigner[brace] then
				foreigner = ' (' .. brace .. ')'
			else
				disambig = ' &nbsp; <small>' .. brace .. '</small>'
			end
		end
	end

	if args.more then
		table.insert( out, frame:callParserFunction{ name = 'DISPLAYTITLE',
				args = 'Состав ' .. lexer.declension( baseName, 1 ) .. ' по состоянию на ' .. tools.dmy( args.more ) } )
	elseif baseName ~= pageTitleText then
--		table.insert( out, frame:callParserFunction{ name = 'DISPLAYTITLE', args = baseName .. ' <small>(' .. braces .. ')</small>' } )
		table.insert( out, frame:callParserFunction{ name = 'DISPLAYTITLE', args = baseName .. foreigner .. disambig .. generation } )
	end

--	table.insert( out, '<div><div class=rkka-editor><div class="panel panel-default"><div class=panel-body><div class=center><b>[https://pamyat-naroda.ru/warunit/?q='
--		.. mw.uri.encode( baseName, 'PATH' )
--		.. ' Память народа] &nbsp; &nbsp; &bull; &nbsp; &nbsp; [https://www.yandex.ru/search/?text='
--		.. mw.uri.encode( pageTitleText, 'QUERY' )
--		.. ' Яндекс] &nbsp; &nbsp; &bull; &nbsp; &nbsp; [https://www.google.com/search?ie=UTF-8&hl=ru&q='
--		.. mw.uri.encode( pageTitleText, 'PATH' )
--		.. ' Google] &nbsp; &nbsp; &bull; &nbsp; &nbsp; [https://www.bing.com/search?q='
--		.. mw.uri.encode( pageTitleText, 'PATH' )
--		.. ' Bing]</b></div></div></div></div></div>'
--	)
	local samenameX = cargo.query( 'unitpages', 'unit',
		{ where = 'unit LIKE "' .. baseName .. ' (%" OR unit="' .. baseName .. '"' } )
	local samename = {}
	for _, v in ipairs( samenameX ) do
		samename[v.unit] = true
	end

	local ctgtable
	local ctg = args['категория']
	local nom, gen
	if not ctg then
		ctg = report.simplecat( baseName ) .. foreigner
		ctg = mw.ustring.lower( mw.ustring.sub( ctg, 1, 1 ) ) .. mw.ustring.sub( ctg, 2, -1 )
	end
	if not cat.names[ctg] then
		if mode ~= 'new' then
			error( 'Необходимо указать существующую категорию формирования вместо «' .. ctg .. '».' )
		end
		ctgtable = nil
		nom = 'формирование'
		gen = 'формирования'
	else
		ctgtable = cat.names[ctg]
		nom = ctgtable.group
		gen = cat.groups[ctgtable.group].gen or 'формирования'
	end

	if args.more then
		table.insert( out, '<p class=lead><i>На этой странице собраны сведения о составе '
			.. lexer.declension( baseName, 1 ) .. ' по состоянию на ' .. tools.dmy( args.more )
			.. ' в соответствии с данными справочника Генерального штаба ВС СССР '
			.. '«[[Project:Научно-справочный труд «Боевой состав Советской Армии»|Боевой состав Советской Армии]]».</i></p>' )
	else
		table.insert( out, '<p class=lead><i>Сведения об упоминаниях '
			.. ( lexer.declension( baseName, 1 ) or ( '‘' .. baseName .. '’' ) ) .. ' в справочнике Генерального штаба ВС СССР '
			.. '«[[Project:Научно-справочный труд «Боевой состав Советской Армии»|Боевой состав Советской Армии]]»'
			.. ', а также (<abbr title="К настоящему времени в указатель внесены не все перечни">частично</abbr>)'
			.. ' в [[РККА:Перечни воинских объединений, соединений, частей и учреждений, входивших в состав действующей армии'
			.. '|Перечнях воинских объединений, соединений, частей и учреждений, входивших в состав действующей армии]]'
			.. '.</i></p>' )
	end

	local descriptors = collectRedirect( pageTitleText )
	if not args.more then
		if next( descriptors ) then
			table.insert( out, [==[
<div class="panel panel-default">
<div class="panel-heading">
<div class="small pull-right in collapse incexc" data-toggle="collapse" data-target=".incexc" >[<i>[[#0|показать]]</i>]</div>
<div class="small pull-right collapse incexc" data-toggle="collapse" data-target=".incexc">[<i>[[#0|скрыть]]</i>]</div>Обозначения ]==] .. gen .. [==[</div>
<div class="panel-body collapse incexc"><p class=small>''В «[[Project:Научно-справочный труд «Боевой состав Советской Армии»|Боевом составе Советской Армии]]» и [[РККА:Перечни воинских объединений, соединений, частей и учреждений, входивших в состав действующей армии|Перечнях]] для одного и того же формирования могли использоваться различные обозначения и, наоборот, в некоторых случаях одно и то же обозначение относилось к разным воинским формированиям.''</p>
<p>]==] .. pageTitleText .. [==[ упоминается под следующими наименованиями:
<div class="panel panel-default"><table class="table">
<tr class=small><th>Наименование</th><th>Период</th><th>Подчинение</th></tr>
]==] )
			for _, dsc in ipairs( descriptors ) do
				table.insert( out, '<tr class=amb-inc>' )
				if dsc.inc and ( #dsc.inc ~=1 or dsc.inc[1].from ~= '' or dsc.inc[1].to ~= '' or dsc.inc[1].tops or dsc.inc[1].topsDirectly ) then
					table.insert( out, '<td rowspan=' .. #dsc.inc .. '>[[' .. dsc.unit .. ']]</td>' )
					local tr = nil
					for _, clause in ipairs( dsc.inc ) do
						table.insert( out, tr )
						if clause.from == '' and clause.to == '' then
							table.insert( out, '<td class=small><i>любое время</i></td>' )
						else
							table.insert( out, '<td>' .. report.printDate( clause.from ) .. '-' .. report.printDate( clause.to ) .. '</td>' )
						end

						if clause.tops or clause.topsDirectly then
							local x = {}
							if clause.tops then
								table.insert( x, '[[' .. table.concat( clause.tops, ']],<br>[[' ) .. ']]' )
							end
							if clause.topsDirectly then
								table.insert( x, '[[' .. table.concat( clause.topsDirectly, ']] <small><i>(непосредственное подчинение)</i></small>,<br>[[' )
									.. ']] <small><i>(непосредственное подчинение)</i></small>' )
							end
							table.insert( out, '<td>' .. table.concat( x, ',<br>' ) .. '</td>' )
						else
							table.insert( out, '<td class=small><i>любое подчинение</i></td>' )
						end
						table.insert( out, '</tr>' )
						tr = '<tr class=amb-inc>'
					end
				else
					table.insert( out, '<td>[' .. tostring( mw.uri.fullUrl( dsc.unit, 'redirect=no' ) ) .. ' ' .. dsc.unit .. ']</td>' )
					if dsc.exc then
						table.insert( out, '<td class=small colspan=2><i>все упоминания <b>(кроме указанных исключений)</b></i></td></tr>' )
					else
						table.insert( out, '<td class=small colspan=2><i>все упоминания (независимо от периода и подчиненности)</i></td></tr>' )
					end
				end

				if dsc.exc then
					table.insert( out, '<tr class=amb-exc>' )
					table.insert( out, '<td rowspan=' .. #dsc.exc .. '> <i>&nbsp; &nbsp; — &nbsp; за исключением</i></td>' )
					local tr = nil
					for _, clause in ipairs( dsc.exc ) do
						table.insert( out, tr )
						if clause.from == '' and clause.to == '' then
							table.insert( out, '<td class=small><i>любое время</i></td>' )
						else
							table.insert( out, '<td>' .. report.printDate( clause.from ) .. '-' .. report.printDate( clause.to ) .. '</td>' )
						end

						if clause.tops or clause.topsDirectly then
							local x = {}
							if clause.tops then
								table.insert( x, '[[' .. table.concat( clause.tops, ']],<br>[[' ) .. ']]' )
							end
							if clause.topsDirectly then
								table.insert( x, '[[' .. table.concat( clause.topsDirectly, ']] <small><i>(непосредственное подчинение)</i></small>,<br>[[' )
									.. ']] <small><i>(непосредственное подчинение)</i></small>' )
							end
							table.insert( out, '<td>' .. table.concat( x, ',<br>' ) .. '</td>' )
						else
							table.insert( out, '<td class=small><i>произвольное подчинение</i></td>' )
						end
						table.insert( out, '</tr>' )
						tr = '<tr class=amb-exc>'
					end
				end
			end
			table.insert( out, '</table></div></div></div>' )
		end
	end

	local where = { 't0.unit="' .. pageTitleText .. '"' }
	local allunits = { [pageTitleText] = true }
	local enumunits = { [pageTitleText] = true }
	for _, dsc in ipairs( descriptors ) do
		allunits[dsc.unit] = true
		local unit = 't0.unit="' .. dsc.unit .. '"'
		if dsc.inc then
			enumunits[dsc.unit] = true
			unit = unit .. ' AND (' .. sqlIncExc( dsc.inc ) .. ')'
		end
		if dsc.exc then
			unit = unit .. ' AND NOT (' .. sqlIncExc( dsc.exc ) .. ')'
		end
		table.insert( where, unit )
	end

	where = table.concat( where, ' OR ' )
	if args.more then
--		where = '(' .. where .. ') AND t0.fix="' .. args.more .. '"'
--		table.insert( out, '<h3>Состав ' .. gen .. ' по состоянию на '
--			.. string.sub( args.more, 9, 10 ) .. '.' .. string.sub( args.more, 6, 7 ) .. '.'
--			.. string.sub( args.more, 1, 4 ) .. '</h3>' )
		table.insert( out, '<p class=small>[' .. tostring( mw.uri.fullUrl( pageTitleText ) ) .. ' <i>Вернуться на основную страницу формирования</i>]</p>' )
		table.insert( out, p.more( where, pageTitleText, args.more ) )
		do --
			local lexer = require( 'Module:Lexer' )
			local gen = lexer.declension( pageTitleText, 1 ) or ( '‘' .. pageTitleText .. '’' )
			local add = {}
			for u, _ in pairs( allunits ) do
				table.insert( add, u )
			end
			-- Боевой состав ххх. Подчинение ХХХ.
			table.insert( out, frame:callParserFunction{ name = '#seo', args = { '',
					description = 'Состав ' .. gen .. ' на ' .. string.sub( args.more, 9, 10 ) .. '.'
						.. string.sub( args.more, 6, 7 ) .. '.' .. string.sub( args.more, 1, 4 ),
					keywords = 'боевой состав Советской Армии,Великая Отечественная война,состав,' .. table.concat( add, ',' ),
				}
			} )
		end
		table.insert( out, '<hr>' )
		return table.concat( out )
	end

	for u, _ in pairs( allunits ) do
		samename[u] = nil
	end
	if next( samename ) then
		samenameX = {}
		for u, _ in pairs( samename ) do
			table.insert( samenameX, u )
		end
		table.sort( samenameX )
		table.insert( out, '<p>Имеются другие формирования с таким же названием: [['
			.. table.concat( samenameX, ']], [[' ) .. ']].</p>' )
	end

	if ctgtable then
		local num = string.match( pageTitleText, '^(%d+)' )
		if num then
			local similarPattern = ctgtable.similar or {}
			table.insert( similarPattern, ctg )
			local similar = {}
			local query = cargo.query( 'unitpages', 'unit,special', {
					where = 'number=' .. num .. ' AND (class="' .. table.concat( similarPattern, '" OR class="' ) .. '")',
				} )
--			for _, u in ipairs( similarPattern ) do
--				local query = cargo.query( 'unitpages', 'unit,special', {
--						where = '(unit LIKE "' .. num .. ' %' .. u .. '%" OR unit LIKE "' .. num .. '-%' .. u .. '%")'
--					} )
			if #query ~= 0 then
				for _, v in ipairs( query ) do
					similar[v.unit] = true
				end
			end
			for u, _ in pairs( allunits ) do
				similar[u] = nil
			end
			for u, _ in pairs( samename ) do
				similar[u] = nil
			end
			local str = {}
			for u, _ in pairs( similar ) do
				table.insert( str, u )
			end
			if #str ~= 0 then
				table.insert( out, '<p class=similar-unit>Имеются другие формирования с похожими или связанными названиями: [['
					.. table.concat( str, ']], [[' ) .. ']].</p>' )
			end
		end
		table.insert( out, '[[Category:' .. ctg .. '|' .. string.sub( '0000' .. ( num or '' ), -4, -1 ) .. pageTitleText .. ']]' )
	end



	local parents, timeline = p.parents( where ) -- делаем сейчас, чтобы заполнить значения first и last

	table.insert( out, frame:expandTemplate{ title = 'Таблица страниц', args = {
		unit = pageTitleText,
		class = ctg,
		number = string.match( pageTitleText, '^%d+' ),
		guard = string.match( pageTitleText, 'гв%. ' ) ~= nil,
		standalone = string.match( pageTitleText, 'отд%. ' ) ~= nil,
		first = first,
		last = last,
		special = nil,
	} } )

	do
		local lexer = require( 'Module:Lexer' )
		local gen = lexer.declension( pageTitleText, 1 ) or ( '‘' .. pageTitleText .. '’' )
		local add = {}
		for u, _ in pairs( allunits ) do
			table.insert( add, u )
		end
		-- Боевой состав ххх. Подчинение ХХХ.
		table.insert( out, frame:callParserFunction{ name = '#seo', args = { '',
				description = 'Боевой состав и подчинение ' .. gen .. '.',
				keywords = 'боевой состав Советской Армии,Великая Отечественная война,' .. table.concat( add, ',' ),
			}
		} )
	end



	if parents then
		table.insert( out, '<br><div style="border: 1px solid #bbb; padding: 12px 4px; height: 56px; border-radius: 10px">' )
		table.insert( out, timeline )
		table.insert( out, '<div class="tl-sc sc-a">1941</div>'
			.. '<div class="tl-sc sc-b">1942</div><div class="tl-sc sc-a">&nbsp;</div>'
			.. '<div class="tl-sc sc-b">1943</div><div class="tl-sc sc-a">&nbsp;</div>'
			.. '<div class="tl-sc sc-b">1944</div><div class="tl-sc sc-a">&nbsp;</div>'
			.. '<div class="tl-sc sc-b">1945</div><div class="tl-sc sc-c">&nbsp;</div>'
			.. '</div><br />' )
		table.insert( out, '<h3>Подчинение</h3>\n' )
		if args['много'] then
			table.insert( out, '<div class="no-double-warning">' )
		end
		table.insert( out, parents )
		if args['много'] then
			table.insert( out, '</div>' )
		end
		global.set( 'PageIsNotEmpty', true )
	else
		table.insert( out, '<p>В справочнике «Боевой состав Советской Армии» нет упоминаний ' .. gen .. '.</p>' )
	end

	local names = {}
	for u, _ in pairs( enumunits ) do
		table.insert( names, u )
	end

	if part then
		global.set( 'PAGE-WHERE', where )
		global.set( 'PAGE-GEN', gen )
		global.set( 'PAGE-UNITS', names )
		table.insert( out, '<h3>Состав ' .. gen .. '</h3>\n' )

		return ref.refReturn( table.concat( out ) )
	end

	do
		local children = p.children( where, pageTitleText )
		if children then
			table.insert( out, '<h3>Состав ' .. gen .. '</h3>\n' )
			table.insert( out, children )
			global.set( 'PageIsNotEmpty', true )
		end
	end

	return p._unitPart2( out, where, gen, names )
end

function p._unitPart2( out, where, gen, enumunits )
--	table.insert( out, mw.dumpObject( where ) .. mw.dumpObject( enumunits ) )
	if not where then
		where = global.get( 'PAGE-WHERE' )
		gen = global.get( 'PAGE-GEN' )
		enumunits = global.get( 'PAGE-UNITS' )
	end
	local separate = p.separate( where )
	if separate then
		table.insert( out, '<h3>Отдельно действующие формирования из состава ' .. gen .. '</h3>\n' )
		table.insert( out, separate )
		global.set( 'PageIsNotEmpty', true )
	end

	local Enumeration = require( 'Module:Enumeration' )
	local enumtext = Enumeration.unitQuery( enumunits )
	if enumtext then
		table.insert( out, '<h3>Упоминания ' .. gen .. ' в «Перечнях»</h3>\n' )
		table.insert( out, enumtext )
		global.set( 'PageIsNotEmpty', true )
	end

	local linksout = require( 'Module:LinksOut' )
	local links = linksout.collect( enumunits )
	if links then
		table.insert( out, '<h3>Ссылки</h3>\n' )
		table.insert( out, links )
		global.set( 'PageIsNotEmpty', true )
	end

	if not global.get( 'PageIsNotEmpty' ) then
		table.insert( out, '[[Категория:Пустая страница формирования]]' )
	end

	table.insert( out, ref.refOut() )

	return table.concat( out )
end


function p.NewArticleText( frame )
	local args = tools.checkargs( frame:getParent().args, {	true } )
	return p._unit( args, frame, 'new' )
end

function p.Unit( frame )
	local args = tools.checkargs( frame:getParent().args, {
--			['включить'] = true, ['исключить'] = true,
			['категория'] = true,
			['БС'] = true, -- не используется, надо вычистить из вызовов
			['годы'] = true, ['много'] = true,
		} )
	local ctg = {}
	for u, _ in pairs( args ) do
		table.insert( ctg, '[[Категория:Формирование:Параметр ' .. u .. ']]' )
	end
	if ( frame.args.more or '' ) ~= '' then
		args.more = frame.args.more
		args['годы'] = nil
	end
	return table.concat( ctg ) .. p._unit( args, frame, false, args['годы'] )
end

function p._Children( frame )
	-- Это вызывается из {{ состав по годам }}
	local args = tools.checkargs( frame.args, { true, true } )
	local where = global.get( 'PAGE-WHERE' )
	if not where then -- это страница MORE
		return
	end
	local gen = global.get( 'PAGE-GEN' )
	local enumunits = global.get( 'PAGE-UNITS' )
	ref.refStart()
	if args[1] then
		return ref.refReturn(p.children( where, mw.title.getCurrentTitle().text, nil, args[1], args[2] ))
	end
	return p._unitPart2( {}, where, gen, enumunits )
end

function p.Redirect( frame )
	local args = tools.checkargs( frame:getParent().args, {
			['категория'] = true,
		} )
	return p._unit( args, frame, 'redirect' )
end

function p.more( where, father, date )
	where = '(' .. where .. ') AND t0.fix="' .. date .. '"'
	local query_tables =
		'units=t0, units=t1, units=t2, units=t3, units=t4, units=t5, units=t6, '
			.. --[['units=t0s,]] 'units=t1s, units=t2s, units=t3s, units=t4s, units=t5s, units=t6s'
	local query_fields =
		't0.fix=date, t0.war=war, '
			.. 't0.unit=id0, t0.addendum=add0, t0.ref=ref0, t0.creating=form0, t0.ass=ass0, t0.tab=tab0, t0.hq=hq0, t0.fixunit=porno0,  ' -- t0s.unit=s_id0, t0s.addendum=s_add0, t0s.ref=s_ref0, '
			.. 't1.unit=id1, t1.addendum=add1, t1.ref=ref1, t1.creating=form1, t1.ass=ass1, t1.tab=tab1, t1.hq=hq1, t1.fixunit=porno1,  t1s.unit=s_id1, t1s.addendum=s_add1, t1s.ref=s_ref1, '
			.. 't2.unit=id2, t2.addendum=add2, t2.ref=ref2, t2.creating=form2, t2.ass=ass2, t2.tab=tab2, t2.hq=hq2, t2.fixunit=porno2,  t2s.unit=s_id2, t2s.addendum=s_add2, t2s.ref=s_ref2, '
			.. 't3.unit=id3, t3.addendum=add3, t3.ref=ref3, t3.creating=form3, t3.ass=ass3, t3.tab=tab3, t3.hq=hq3, t3.fixunit=porno3,  t3s.unit=s_id3, t3s.addendum=s_add3, t3s.ref=s_ref3, '
			.. 't4.unit=id4, t4.addendum=add4, t4.ref=ref4, t4.creating=form4, t4.ass=ass4, t4.tab=tab4, t4.hq=hq4, t4.fixunit=porno4,  t4s.unit=s_id4, t4s.addendum=s_add4, t4s.ref=s_ref4, '
			.. 't5.unit=id5, t5.addendum=add5, t5.ref=ref5, t5.creating=form5, t5.ass=ass5, t5.tab=tab5, t5.hq=hq5, t5.fixunit=porno5,  t5s.unit=s_id5, t5s.addendum=s_add5, t5s.ref=s_ref5, '
			.. 't6.unit=id6, t6.addendum=add6, t6.ref=ref6, t6.creating=form6, t6.ass=ass6, t6.tab=tab6, t6.hq=hq6, t6.fixunit=porno6,  t6s.unit=s_id6, t6s.addendum=s_add6, t6s.ref=s_ref6, '
			.. 't0._pageName=page, t0.page=bookpage'
	local query_args = {
			join    =  't0.fixunit=t1.fixparent, ' -- t0.fixstruct=t0s.fixunit, '
					.. 't1.fixunit=t2.fixparent, t1.fixstruct=t1s.fixunit, '
					.. 't2.fixunit=t3.fixparent, t2.fixstruct=t2s.fixunit, '
					.. 't3.fixunit=t4.fixparent, t3.fixstruct=t3s.fixunit, '
					.. 't4.fixunit=t5.fixparent, t4.fixstruct=t4s.fixunit, '
					.. 't5.fixunit=t6.fixparent, t5.fixstruct=t5s.fixunit, '
					.. 't6.fixstruct=t6s.fixunit ',
			where   = where,
			orderBy = 'date, porno1, porno2, porno3, porno4, porno5, porno6',
			limit   = 5000,
		}

	local children = cargo.query( query_tables, query_fields, query_args )
	local tt = require( 'Module:Traversal' )
	tt.init( children, father )
	local res = { '<b>' .. father .. '</b><div class=tree-level>' }
	local num = 0
	local apply
--	local pack = {}
	while true do
		local el = tt.get()
		if not el then
--			table.insert( res, table.concat( pack ) )
			break
		end
		local elt = el[1]
		if type( elt ) == 'number' then
--			table.insert( pack, '<p>' .. report.outEl( el[2], elt, 2, true ) .. '</p>' ) -- [[' .. el[2]['id'..elt] .. ']]</p>' )
			local itag
			if el[3] then
				num = num + 1
				apply = true
				itag = '<div style="display:inline-block; width:1em; text-align:center">[[#0|'
					.. '<span class="collapse in tree-level-' .. num ..'" data-toggle="collapse" data-target=".tree-level-' .. num ..'"><i class="fa fa-caret-down"></i></span>'
					.. '<span class="collapse tree-level-' .. num ..'" data-toggle="collapse" data-target=".tree-level-' .. num ..'"><i class="fa fa-caret-right"></i></span>'
					.. ']]</div>&nbsp;'
			else
				apply = nil
				itag = '<div style="display:inline-block; width:1em; text-align:center">&#9675;</div>&nbsp;'
			end
			table.insert( res, '<div class=line>' .. itag .. report.outEl( el[2], elt, 2, true ) .. '</div>' ) -- [[' .. el[2]['id'..elt] .. ']]</p>' )
		else
--			table.insert( res, table.concat( pack ) )
--			pack = {}
			if elt == '{' then
			elseif elt == '[' then
				table.insert( res, '<div>' )
			elseif elt == '(' then
				if apply then
					table.insert( res, '<div class="tree-level collapse in tree-level-' .. num .. '">' )
					apply = nil
				else
					table.insert( res, '<div class=tree-level>' )
				end
			elseif elt == ')' or elt == ']' then
				table.insert( res, '</div>' )
			else
			end
		end
	end
	table.insert( res, '</div>' )
	return table.concat( res )


end

--[===[
function p.Synonym( frame )
	local args = tools.checkargs( frame:getParent().args, {
			true, ['категория'] = true,
		} )
	local pageTitle = mw.title.getCurrentTitle().text
	local ctgtable
	local ctg = args['категория']
	local gen
	if not ctg then
		ctg = report.category( pageTitle )
	end
	ctgtable = cat.names[ctg]
	if not ctgtable then
		error( 'Необходимо указать существующую категорию формирования вместо «' .. ctg .. '».' )
	else
		gen = cat.groups[ctgtable.group].gen or 'формирования'
	end
	table.insert( out, frame:expandTemplate{ title = 'Таблица страниц', args = {
		unit = unit,
		class = ctg,
		number = string.match( unit, '^%d+' ),
		guard = string.match( unit, 'гв%. ' ) ~= nil,
		standalone = string.match( unit, 'отд%. ' ) ~= nil,
		first = first,
		last = last,
		special = x,
	} } )
end
--]===]
function p.ReBS_test( frame )
	return p.children( '(t0.unit="Действующая армия" AND t0.fix="1941-06-22")' )
end

return p