Модуль:ReBS

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

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

local p = {}

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 DIVIDER = ',  '
report.space = ' '
report.pageMode = false

local tabs = {
		'стр', 'арт', 'мех', 'ввс', 'инж',
		[''] = 0,
		['стр'] = 1,
		['арт'] = 2,
		['пва'] = 2,
		['пва-class'] = '5a',
		['мех'] = 3,
		['ввс'] = 4,
		['инж'] = 5,
		['огн'] = 5,
		['огн-class'] = '5a',
	}


function p.reBS( chapter, date )
	local where = 't0.unit="' .. chapter .. '" 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.asstab=asstab0, t0.page=page0, 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.asstab=asstab1, t1.page=page1, 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.asstab=asstab2, t2.page=page2, 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.asstab=asstab3, t3.page=page3, 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.asstab=asstab4, t4.page=page4, 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.asstab=asstab5, t5.page=page5, 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.asstab=asstab6, t6.page=page6, t6.fixunit=porno6,  t6s.unit=s_id6, t6s.addendum=s_add6, t6s.ref=s_ref6, '
			.. 't0._pageName=page'
	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 )
	if #children == 5000 then
		query_args.offset = 5000
		query_args.limit = 1000
		local children1 = cargo.query( query_tables, query_fields, query_args )
		for _, ch in ipairs( children1 ) do
			table.insert( children, ch )
		end
	end
	assert( #children < 6000 )

	local str = {}
	local flat = {}
	local prev = { ass1 = '' }
	local gene = {}
	local Lprev = 0
	local lastTab = nil
	local function closeFlat()
		table.insert( flat, report.popBuffer() )
		table.insert( str, table.concat( flat, DIVIDER ) )
		flat = {}
	end
	local function closeRow(  )
		if lastTab then
			closeFlat()
			table.insert( str, '</p></div></div></div>' )
			lastTab = nil
		end
	end

	local assMaxChild = {}
	local xDebug = 0

	for _, child in ipairs( children ) do
		if xDebug ~= 0 then
			mw.logObject( child ) -- do return end
			xDebug = xDebug-1
		end
		if child.id1 ~= '' then
			local diff
			for i = 1, Lprev do
				if prev['porno'..i] ~= child['porno'..i] then
					diff = i
					break
				end
			end
			if not diff then
				if Lprev ~= 0 then -- предыдущий объект был, но он полностью покрывается нашим, без единого отличия. Такого быть не может, потому что SQL отдает только оконечные листья, а не узлы
					error( 'Несогласованное состояние БД: \n((' .. mw.dumpObject( prev ) .. '))--\n\n--[[' .. mw.dumpObject( child )  )
				else -- А если предыдущего объекта не было, то расхождения начинаются с 1 элемента
					diff = 1
				end
			end
			-- если diff == #prev, то это очередной элемент в плоской последовательности. Возможно, потребуется сменить таб. А если новый элемент с ass, то и закрыть ряд
			-- если diff < #prev, то нам нужно закрыть (#stack - diff) элементов. Это могут быть объединения или корпуса
			-- diff > #prev бывает только для самого первого элемента

			local comma
			if diff < Lprev then
				closeFlat()
				for i = Lprev-1, diff, -1 do
					if prev['ass'..i] == '' then
						table.insert( str, ')</span>' )
						comma = true
					else
						break -- если встретилось объединение, то скобки больше не нужны
					end
				end
			end

			if prev['ass'..diff] ~= '' or child['ass'..diff] ~= '' then
				closeRow()
			end

			-- если самый значительный закрываемый уровень (prev['ass'..diff]) более весом, чем тот уровень, который будет открываться (child['ass'..diff]),
			-- то необходимо вставить строчку «непосредственное подчинение» с нужной окраской.
			if prev['ass'..diff] ~= '' then
				if child['ass'..diff] == '' or prev['ass'..diff] < child['ass'..diff] then
					local chain = ''
					for i = diff-1, 1, -1 do
						chain = chain .. ' / [[' .. child['id'..i] .. ']]' -- в этой части child==prev
					end
					if chain == '' then
						chain = ' / Ставка'
					end
					local page
					if child['page'..diff] ~= ''  then
						page = ' &nbsp; <small>[' .. mw.site.server .. mw.site.scriptPath .. '/images/ExtFiles/'
							.. string.sub( date, 1, 4 ) .. '.pdf#page=' .. child['page'..diff]
							.. ' <i class="fa fa-file-o fa-rotate-90" title="Оригинал, стр. ' .. child['page'..diff] .. '"></i>]</small>'
--						page = '<div class=pull-right title="Оригинал">[' .. mw.site.server .. mw.site.scriptPath .. '/images/ExtFiles/'
--							.. string.sub( date, 1, 4 ) .. '.pdf#page=' .. child['page'..diff]
--							.. ' <i class="fa fa-file-o fa-rotate-90"></i>]</div>'
					else
						page = ''
					end
					table.insert( str, '<div class="bs-ext-assoc-' .. ( assMaxChild[diff-1] or 2 ) .. '"><div class="bs-int-assoc">Непосредственное подчинение' .. chain .. page .. '</div></div>' )
				end
			end

			-- теперь, наконец, переходим к собственно новым элементам
			local intab
			for j = diff, 6 do
				if child['ass'..j] == '' then
					intab = j
					break
				end
				local chain = ''
				for i = j-1, 1, -1 do
					chain = chain .. ' / [[' .. child['id'..i] .. ']]'
				end

				if child['asstab'..j] ~= '' then
					lastTab = tabs[1]
					table.insert( str, '<div class="bs-raw-wrap"><div class="bs-tab-wrap"><div class="bs-ext-assoc-'  .. child['ass'..j] .. '"><p class="bs-int-assoc">( ! )'.. report.outEl( child, j, 2, true ) )
				else
					local page
					if child['page'..j] ~= ''  then
						page = ' &nbsp; <small>[' .. mw.site.server .. mw.site.scriptPath .. '/images/ExtFiles/'
							.. string.sub( date, 1, 4 ) .. '.pdf#page=' .. child['page'..j]
							.. ' <i class="fa fa-file-o fa-rotate-90" title="Оригинал, стр. ' .. child['page'..j] .. '"></i>]</small>'
--						page = '<div class=pull-right title="Оригинал">[' .. mw.site.server .. mw.site.scriptPath .. '/images/ExtFiles/'
--							.. string.sub( date, 1, 4 ) .. '.pdf#page=' .. child['page'..j]
--							.. ' <i class="fa fa-file-o fa-rotate-90"></i>]</div>'
					else
						page = ''
					end
					table.insert( str, '<div class="bs-ext-assoc-' .. child['ass'..j] .. '"><div class="bs-int-assoc">' .. report.outEl( child, j, 2, true ) .. chain .. page .. '</div></div>' )
				end
				assMaxChild[j] = nil
				if j ~= 1 then
					if ( assMaxChild[j-1] or '9' ) > child['ass'..j] then
						assMaxChild[j-1] = child['ass'..j]
					end
				end
			end
			assert( intab )

			if child['ass'..diff] ~= ''then
				local upGene = string.match( child['id'..(intab-1)], '%(([^()]+)%)$' )
				if upGene and type( report.knownBrackets[upGene] ) ~= 'string' then
					upGene = nil
				end
				gene[intab-1] = upGene
			end

			local newTab = child['tab'..intab]
			local tabOut, tabWrap = '', '<div class="bs-tab-wrap">'
			if newTab ~= '' then -- если нового таба нет, то ничего больше не нужно, т. к. тогда мы закрыли прежний в самом начале
				if lastTab ~= newTab then -- если табы совпадают, то ничего не нужно
					closeFlat()
					local no, nn
					nn = tabs[newTab]
					if lastTab then
						no =  tabs[lastTab]
						if no == nn then
							tabOut = '</p></div>'
							tabWrap = ''
						elseif no > nn then
							closeRow()
							tabOut = '<div class="bs-raw-wrap">'
							no = 0
						else
							tabOut = '</p></div></div>'
						end
					else
						tabOut = '<div class="bs-raw-wrap">'
						no = 0
					end
					tabOut = tabOut .. string.rep( '<div class="bs-tab-wrap">&nbsp;</div>', nn-1-no )
					table.insert( str, tabOut .. tabWrap .. '<div class="bs-tab-' .. ( tabs[newTab ..'-class'] or nn ) .. '"><p>' )
				elseif comma then
					table.insert( str, DIVIDER )
				end
			end
			lastTab = newTab

			report.gene = gene[intab-1]
			for j = intab, 6 do
				if child['id'..j] == '' then
					Lprev = j-1
					break
				end
				if child['id'..(j+1)] ~= '' then
					if #flat ~= 0 then
						closeFlat()
						table.insert( str, DIVIDER )
					end
					table.insert( str, report.outEl( child, j, 1, true ) .. ' <span class=childs>(' )
					gene[j] = report.gene
				else
					table.insert( flat, report.outEl( child, j, 1, true, true ) )
				end
			end
			prev = child
		end
	end
	closeRow()
	table.insert( str, ref.refOut() )
	return ref.refReturn( table.concat( str ) )
end

function p.ReBS( frame )
	local args = tools.checkargs( frame:getParent().args, { true, true } )
	return p.reBS( args[1], args[2] )
end

return p