Модуль:Page

Материал из Указатель частей и соединений РККА 1941-1945
Перейти к:навигация, поиск

Для документации этого модуля может быть создана страница Модуль: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 english = mw.getContentLanguage():getCode() == 'en'
local translation, months, showEnDate
if english then
	cat = require( 'Module:Categories.en' ) -- loadData не позволяет пользоваться #...  и т. п.
	translation = {
		'The information is repeated for all intermediate dates. [[#0|Show]]',
		'Expand into a tree',
		'formation',  -- используется для порядкового номера формирования
		'Return to unit main page',
		'There are other units with the same name',

		'There are other units with similar or related names',
		'Subordination',
		'There is no mention of the %s in the reference book “Order of battle of the Soviet Army”.',
		'%s composition',
		'Separately operating subunits',

		'Other common names of the ',
		'',
	}
	months = {
		'January',
		'February',
		'March',
		'April',
		'May',
		'June',
		'July',
		'August',
		'September',
		'October',
		'November',
		'December',
	}
	showEnDate = function( ymd )
		if #ymd == 10 then
			return months[tonumber( string.sub( ymd, 6, 7 ) )] .. ' ' .. tonumber( string.sub( ymd, 9, 10 ) ) .. ', ' .. string.sub( ymd, 1, 4 )
		elseif #ymd == 7 then
			return months[tonumber( string.sub( ymd, 6, 7 ) )] .. ', ' .. string.sub( ymd, 1, 4 )
		else
			return ymd
		end
	end
else
	cat = require( 'Module:Categories' ) -- loadData не позволяет пользоваться #...  и т. п.
	translation = {
		'Сведения повторяются на все промежуточные даты. [[#0|Показать?]]',
		'Показать развернутый список без сокращений',
		'формирование',  -- используется для порядкового номера формирования
		'Вернуться на основную страницу формирования',
		'Имеются другие формирования с таким же названием',

		'Имеются другие формирования с похожими или связанными названиями',
		'Подчинение',
		'В справочнике «Боевой состав Советской Армии» нет упоминаний %s.',
		'Состав %s',
		'Отдельно действующие формирования из состава %s',

		'Другие встречающиеся наименования ',
		'',
	}
end



local first, last

local DIVIDER = ',  '

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 show 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;' .. translation[1] .. '</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="' .. translation[2] .. '"></i>]</p>' )
			end
		end
	end
	table.insert( res, '</div>' )
	if #children >= 9999 then
		table.insert( res, '<p class=error>Сведения о составе чересчур объемны (' .. #children .. ')! Выдача прервана.</p>[[Category:Слишком большие сведения о составе]]' )
	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] ),
				selector = row.selector,
			} )
	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
	table.insert( out, frame:preprocess( '<indicator name=link-rkka><span class="d-none admin-view">[{{fullurl:rkka:' .. pageTitleText .. '|action=edit&redirect=no}} <i class="fa fa-link"></i>]</span></indicator>' ) )

	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] .. ' ' .. translation[3] .. '</i>'
			elseif dataOut.foreigner[brace] then
				foreigner = ' (' .. brace .. ')'
			else
				disambig = ' &nbsp; <small>' .. brace .. '</small>'
			end
		end
	end

	if args.more then
		local title
		if english then
			title = 'Order of battle of the ' .. baseName .. ' as at ' .. showEnDate( args.more )
		else
			title = 'Состав ' ..  lexer.declension( baseName, 1 ) .. ' по состоянию на ' .. tools.dmy( args.more )
		end
		table.insert( out, frame:callParserFunction{ name = 'DISPLAYTITLE', args = title } )
	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="card panel-default"><div class=card-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 .. '" ) AND ( special IS NULL OR special <> "m" )' } )
	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
		if not english then
			ctg = mw.ustring.lower( mw.ustring.sub( ctg, 1, 1 ) ) .. mw.ustring.sub( ctg, 2, -1 )
		end
	end
	if not cat.names[ctg] then
		if mode ~= 'new' then
			error( 'Необходимо указать существующую категорию формирования вместо «' .. ctg .. '».' )
		end
		ctgtable = nil
		if english then
			nom = 'unit'
			gen = 'unit'
		else
			nom = 'формирование'
			gen = 'формирования'
		end
	else
		ctgtable = cat.names[ctg]
		nom = ctgtable.group
		if english then
			gen = nom
		else
			gen = cat.groups[ctgtable.group].gen or 'формирования'
		end
	end

	if args.more then
		if english then
			table.insert( out, '<p class=lead><i>This page contains information about the composition of the '
				.. baseName .. ' as at ' .. showEnDate( args.more )
				.. ' from the reference book of the General Staff of the Armed Forces of the USSR '
				.. '“[[Project:Scientific reference book “Order of battle of the Soviet Army”|Order of battle of the Soviet Army]]”.</i></p>' )
		else
			table.insert( out, '<p class=lead><i>На этой странице представлены сведения о составе '
				.. lexer.declension( baseName, 1 ) .. ' по состоянию на ' .. tools.dmy( args.more )
				.. ' в соответствии с данными справочника Генерального штаба ВС СССР '
				.. '«[[Project:Научно-справочный труд «Боевой состав Советской Армии»|Боевой состав Советской Армии]]».</i></p>' )
		end
	else
		if english then
			table.insert( out, '<p class=lead><i>Information about mentions of the ' .. baseName
				.. ' in the reference book of the General Staff of the Armed Forces of the USSR '
				.. '“[[Project:Scientific reference book “Order of battle of the Soviet Army”|Order of battle of the Soviet Army]]”.</i></p>' )
		else
			table.insert( out, '<p class=lead><i>Сведения об упоминаниях '
				.. ( lexer.declension( baseName, 1 ) or ( '‘' .. baseName .. '’' ) ) .. ' в справочнике Генерального штаба ВС СССР '
				.. '«[[Project:Научно-справочный труд «Боевой состав Советской Армии»|Боевой состав Советской Армии]]»'
				.. ', а также (<abbr title="К настоящему времени в указатель внесены не все перечни">частично</abbr>)'
				.. ' в [[РККА:Перечни воинских объединений, соединений, частей и учреждений, входивших в состав действующей армии'
				.. '|Перечнях воинских объединений, соединений, частей и учреждений, входивших в состав действующей армии]]'
				.. '.</i></p>' )
		end
	end

	if english then
		local rus = cargo.query( 'dictionary', 'rus, eng', { where = 'eng="' .. pageTitleText .. '"' } )
		local text = ''
		if #rus > 1 then
			local altArray = {}
			for i = 2, #rus do
				table.insert( altArray, '[[ru:' .. rus[i].rus .. '|' .. rus[i].rus .. ']]' )
			end
			text = ' (' .. table.concat( altArray, ', ' ) .. ')[[Category:Unit name translation issue]]'
		end
		if #rus ~= 0 then
			table.insert( out, '<p>Name in Russian: [[ru:' .. rus[1].rus .. '|' .. rus[1].rus .. ']]' .. text .. '.</p>' )
		else
			table.insert( out, '[[Category:Unit name translation issue]]' )
		end
	end

	local descriptors = collectRedirect( pageTitleText )
	if not args.more then
		local aDsc = {}
		for _, dsc in ipairs( descriptors ) do
			if dsc.selector == ';;;#' then
				table.insert( aDsc, dsc.unit )
			end
		end

		if next( aDsc ) then
			table.insert( out, '<p>' .. translation[11] .. gen .. ': [[' .. table.concat( aDsc, ']], [[' ) .. ']].</p>' )
		end
		table.insert( aDsc, pageTitleText )
		table.insert( out, '<div id=unitpage class=d-none data-list="' .. table.concat( aDsc, '|' ) .. '"></div>' ) -- для js

		if false and next( descriptors ) then -- пока оставляем в коде, отключаем
			table.insert( out, [==[
<div class="card panel-default">
<div class="card-header">
<div class="small pull-right show 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="card-body collapse incexc"><p class=small>''В «[[Project:Научно-справочный труд «Боевой состав Советской Армии»|Боевом составе Советской Армии]]» и [[РККА:Перечни воинских объединений, соединений, частей и учреждений, входивших в состав действующей армии|Перечнях]] для одного и того же формирования могли использоваться различные обозначения и, наоборот, в некоторых случаях одно и то же обозначение относилось к разным воинским формированиям.''</p>
<p>]==] .. pageTitleText .. [==[ упоминается под следующими наименованиями:
<div class="card 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>' .. translation[4] .. '</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>' .. translation[5] .. ': [['
			.. 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="' ) .. '") AND ( special IS NULL OR special <> "m" )' ,
				} )
--			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>' .. translation[6] .. ': [['
					.. 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>' .. translation[7] .. '</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>' .. string.format( translation[8], 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>' .. string.format( translation[9], gen ) .. '</h3>\n' )

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

	do
		local children = p.children( where, pageTitleText )
		if children then
			table.insert( out, '<h3>' .. string.format( translation[9], 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>' .. string.format( translation[10], 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, '[[Category:Пустая страница формирования]]' )
	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, '[[Category:Формирование:Параметр ' .. u .. ']]' )
	end
	if ( frame.args.more or '' ) ~= '' then -- при вызове шаблона параметры url переносятся в аргумент #invoke
		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 show 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 show 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