Модуль:Report

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

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

local report = {}
local ref = require( 'Module:Ref' )
local lexer = require( 'Module:Lexer' )
local global = mw.ext.luaglobal
local redata
local formation

local knownBrackets
local knownBracketsSuperOut
local translation

local english = mw.getContentLanguage():getCode() == 'en'
if english then
	redata = mw.loadData( 'Module:Redata.en' )
	translation = {
		'Separate',
		'Guards',
		'“',
		'”',
		'Only Headquarter',

		"Field Forces",
		"Military districts and inactive fronts",
		'Military District$',
		'inactive forces',
		"Air defense forces on the territory of military districts and inactive fronts",

		'Front − air defense troops$',
		'inactive front',
		"Air Defense Forces of the Country",
		"Air defense forces that covered the objects of the active army",
		'District − air defense troops$',

		'Module:Formation.en',
		'Military District %(I+ formation%)$',
	}

	knownBrackets = {
		['Pol.'] = 'Pol.',
		['Fr.'] = 'Fr.',
		['Hung.'] = 'Hung.',
		['Czech.'] = 'Czech.',
		['Yug.'] = 'Yug.',
		['Rom.'] = 'Rom.',
		['Bulg.'] = 'Bulg.',
		['Mong.'] = 'Mong.',
		['I'] = 1,
		['II'] = 2,
		['III'] = 3,
		['IV'] = 4,
		['V'] = 5,
		['VI'] = 6,
		['I formation'] = 1,
		['II formation'] = 2,
		['III formation'] = 3,
		['IV formation'] = 4,
		['V formation'] = 5,
		['VI formation'] = 6,
	}
	knownBracketsSuperOut = {
		'I formation',
		'II formation',
		'III formation',
		'IV formation',
		'V formation',
		'VI formation',
	}
else
	redata = mw.loadData( 'Module:Redata' )
	translation = {
		'отд%.',
		'гв%.',
		'«',
		'»',
		'Управление без войск',

		'Действующая армия',
		'Военные округа и недействующие фронты',
		'военный округ$',
		'недействующие войска',
		'Войска ПВО на территории военных округов и недействующих фронтов',

		'фронт — войска ПВО$',
		'недействующий фронт',
		'Войска ПВО территории страны',
		'Войска ПВО, прикрывавшие объекты действующей армии',
		'округ — войска ПВО$',

		'Module:Formation',
		'военный округ %(I+ формирования%)$',
	}
	knownBrackets = {
		['Войско Польское'] = 'Войско Польское',
		['ВП'] = 'Войско Польское',
		['фр.'] = 'фр.',
		['венг.'] = 'венг.',
		['чех.'] = 'чех.',
		['югосл.'] = 'югосл.',
		['рум.'] = 'рум.',
		['болг.'] = 'болг.',
		['монг.'] = 'монг.',
		['I'] = 1,
		['II'] = 2,
		['III'] = 3,
		['IV'] = 4,
		['V'] = 5,
		['VI'] = 6,
		['I формирования'] = 1,
		['II формирования'] = 2,
		['III формирования'] = 3,
		['IV формирования'] = 4,
		['V формирования'] = 5,
		['VI формирования'] = 6,
	}
	knownBracketsSuperOut = {
		'I формирования',
		'II формирования',
		'III формирования',
		'IV формирования',
		'V формирования',
		'VI формирования',
	}
end



report.knownBrackets = knownBrackets

local buffer = {}
local  bufferCommon, bufferCommonN, bufferCommonAdd, bufferCommonForm, bufferCommonStruct, bufferCommonHq, bufferCommonGene

report.space = ' '
report.pageMode = true

if english then
	function report.simplecat( str ) -- использует очищенное от скобок наименование
		local a = ( string.match( str, '^(.+)( “.+”)$' ) ) or str

		local b = string.match( a, 'Guards (.+)$' )
		if b then
			if string.find( ' ' .. b, ' Mortar' ) then
				a = 'Guards ' .. b
			else
				a = b
			end
		else
			b = string.match( a, 'Separate (.+)$' )
			if b then
				a = b
			else
				a = ( string.match( a, '^%d[^ ]* (.+)$' ) ) or a
			end
		end
		return a

	end
else
	function report.simplecat( str ) -- использует очищенное от скобок наименование
		local a = ( string.match( str, '^(.+)( «.+»)$' ) ) or str

		local b = mw.ustring.match( a, '[гГ]в%. (.+)$' )
		if b then
			if string.find( ' ' .. b, ' минометн' ) then
				a = 'гв. ' .. b
			else
				a = b
			end
		else
			b = string.match( a, '[оО]тд%. (.+)$' )
			if b then
				a = b
			else
				a = ( string.match( a, '^%d[^ ]* (.+)$' ) ) or a
			end
		end
		return a

	end
end
function report.fuller( str, badAbbr )
	badAbbr = badAbbr or {}
	if badAbbr[str] or redata.Full[str] then
		return badAbbr[str] or redata.Full[str]
	end
	local num, a = string.match( str, '^(%d[^ ]* )(.+)$' )
	if num then
		local gv, otd, otdInc
		a, gv = string.gsub( a, 'гв. ', '' )
		if gv == 1 then
			gv = 'гв. '
		else
			gv = ''
		end
		a, otd = string.gsub( a, 'отд. ', '' )
		if otd == 1 then
			otd = 'отд. '
		else
			otd = ''
		end
		a = badAbbr[a] or redata.Full[a]
		if a then
			a, otdInc = string.gsub( a, 'отд. ', '' )
			if otdInc == 1 then
				otd = 'отд. '
			end
			return num .. otd .. gv .. a
		end
	else
		num, a = string.match( str, '^([^ ]* )(.+)$' )
		if badAbbr[a] or redata.Full[a] then
			return num .. ( badAbbr[a] or redata.Full[a] )
		end
	end
	return str
end

--function report.bigfuller( str, badAbbr )
--	local stored = {}
--	local n
--	repeat
--		str, n = string.gsub( str, ' %(([^()]+)%)', function ( u )
--				if knownBracketsBig[u] then
--					table.insert( stored, knownBracketsBig[u] )
--					return '&' .. string.char( 96 + #stored )
--				else
--					local parts = mw.text.split( mw.text.trim( u ), '%s*,%s*' )
--					for i, part in ipairs( parts ) do
--						local body, ending = string.match( part, '^([^&]+)(.*)$' )
--						parts[i] = lexer.declension( report.fuller( body ), 1, true ) .. ending
--					end
--					table.insert( stored, table.concat( parts, ', ' ) )
--				end
--				return '&' .. string.char( 96 + #stored )
--			end	)
--	until n == 0
--	local body, ending = string.match( str, '^([^&]+)(.*)$' )
--	str = report.fuller( body, badAbbr ) .. ending
--	repeat
--		str, n = string.gsub( str, '&(.)', function ( u )
--				return ' (' .. stored[string.byte( u ) - 96] .. ')'
--			end )
--	until n == 0
--	return str
--end
local function parseList( list, collection )
	local stored = {}
	list = string.gsub( list, '%b()', function( a )
			table.insert( stored, a )
			return '&' .. string.char( 96 + #stored )
		end )
	local parts = mw.text.split( list, '%s*,%s*' )
	for i, part in ipairs( parts ) do
		local lexxx
		part = report.bigfuller( ( string.gsub( part, '&(.)', function ( u )
				return stored[string.byte( u ) - 96]
			end ) ) )
		parts[i], lexxx = lexer.declension( part, 1, true ) -- получаем склоненное+ключ, либо несклоненное+nil
		if collection then
			if not lexxx then
				part = ''
			end
			table.insert( collection, part )
		end
	end
	return parts -- возвращаем список текстов (склоняемых и несклоняемых), а в collection — список склоняемых юнитов (с пустыми текставми вместо несклоняемых)
end


function report.bigfuller( str, badAbbr, parentsCollection )
	local shorted, parent, generation, foreign
	local body, overname = string.match( str, '^(.+) %[(.+)%]$' )
	body = body or str
	repeat
		local  el
		shorted, el = string.match( body, '^(.-)%s+(%b())$' )
		if shorted then
			body = shorted
			el = mw.text.trim( string.sub( el, 2, -2 ) )
			local u = knownBrackets[el]
			if u then
				if type( u ) == 'number' then
					generation = knownBracketsSuperOut[u]
				else
					foreign = u
				end
			else
				parent = el
			end
		end
	until not shorted

	if parent then
		local parts = parseList( parent, parentsCollection )
		parent = ' (' .. string.gsub( table.concat( parts, ', ' ), ' формирования%)', '%)' ) .. ')'
	end

	if overname then
		local overList = {}
		local parts = parseList( overname, overList )
		for i, overUnit in ipairs( overList ) do
			if overUnit ~= '' then
				global.add( 'UNIT-IN-TEXT', overUnit )
				parts[i] = '<span class=unit-in-text data-unit="' .. overUnit .. '">[[' .. overUnit ..'|' .. parts[i] .. ']]</span>'
			end
		end
		overname = table.concat( parts, ', ' )
	end

	if foreign then
		foreign =  ' (' .. foreign .. ')'
	end
	if generation then
		generation =  ' (' .. generation .. ')'
	end
	body = report.fuller( body, badAbbr )
	return body .. ( foreign or '' ) .. ( parent or '' ) .. ( generation or '' ), body .. ( generation or '' ), overname
end


--function report.bigfuller( str, badAbbr, classfunc )
--	classfunc = classfunc or function () return '' end
--	local body = str
--	local shorted, parent, showParent, generation, foreign
--	repeat
--		local  el
--		shorted, el = string.match( body, '^(.-)%s+(%b())$' )
--		if shorted then
--			body = shorted
--			el = mw.text.trim( string.sub( el, 2, -2 ) )
--			local u = knownBrackets[el]
--			if u then
--				if type( u ) == 'number' then
--					generation = knownBracketsSuperOut[u]
--				else
--					foreign = u
--				end
--			else
--				parent = el
--			end
--		end
--	until not shorted

--	if parent then
--		local stored = {}
--		local showed = {}
--		parent = string.gsub( parent, '%b()', function( a )
--				table.insert( stored, a )
--				return '&' .. string.char( 96 + #stored )
--			end )
--		local parts = mw.text.split( parent, '%s*,%s*' )
--		for i, part in ipairs( parts ) do
--			local lexxx
--			part = string.gsub( part, '&(.)', function ( u )
--					return stored[string.byte( u ) - 96]
--				end )
--			part = report.bigfuller( part )
--			parts[i], lexxx = string.gsub( lexer.declension( part, 1, true ), ' формирования%)', '%)' )
--			if lexxx then
--				table.insert( showed, '<span class="unit-top ' .. classfunc( part ) .. '">[[' .. part .. '|' .. parts[i] .. ']]</span>' )
--			else
--				table.insert( showed, part )
--			end
--		end
--		parent = ' (' .. table.concat( parts, ', ' ) .. ')'
--		showParent = ' (' .. table.concat( showed, ', ' ) .. ')'
--	end

--	if foreign then
--		foreign =  ' (' .. foreign .. ')'
--	end
--	if generation then
--		generation =  ' (' .. generation .. ')'
--	end
--	local a = report.fuller( body, badAbbr ) .. ( foreign or '' )
--	local u = a .. ( parent or '' ) .. ( generation or '' )
--	local spanu = classfunc( u )
--	if spanu ~= '' then
--		a = '<span class="' .. spanu .. '">' .. a .. '</span>'
--	end
--	return u, a, showParent, generation
--end

function report.shorter( str, plural )
	-- отделяем хвосты
	local brackets, quotes, numb, name, otd, gv
	local a, b
	local abbr

	local function acheck( u, plural )
		if english then
			if not plural then
				return u
			end
			local body2, top = string.match( u, '^(.-) of( .+)$' )
			if not body2 then
				body2, top = u, ''
			end
			local words = mw.text.split( body2, ' ' )
			local main, plw
			for i = #words, 1, -1 do
				plw = redata.Plurals[words[i]]
				if plw then
					main = i
					break
				end
			end
			if not main then
				return nil
			end
			local pre, post
			if main ~= 1 then
				pre = table.concat( words, ' ', 1, main-1 ) .. ' ' .. plw
			else
				pre = plw
			end
			if main ~= #words then
				post = ' ' .. table.concat( words, ' ', main+1 )
			else
				post = ''
			end
			return pre .. post .. top
		else
			local descr = redata.Descr[u]
			if not descr then
				return nil
			end
			if plural then
				return descr[2] or descr[1]
			end
			return descr[1]
		end
	end

	a, brackets = string.match( str, '^(.-) %((.+)%)$' )
	local owngene
	if not a then
		a = str
		brackets = ''
	else
		local bracketsA = mw.text.split( brackets, ') (', true )
		brackets = ''
--		for i = 1, #bracketsA do
--			if knownBrackets[bracketsA[i]] then
--				brackets = brackets .. ' (' .. bracketsA[i] .. ')'
--			end
--		end
		for _, bra in ipairs( bracketsA ) do
			local known = knownBrackets[bra]
			if known then
				if type( known ) == 'string' then
					if report.gene then
						if known ~= report.gene then
							error( 'Межнациональная рознь: ' .. report.gene .. ' содержит ' .. known )
						else
							owngene = known
						end
					else
						owngene = known
						brackets = brackets .. ' (' .. known .. ')'
					end
				else
--					brackets = brackets .. ' (' .. bra .. ')'
				end
			end
		end
	end
	if report.gene and not owngene then
		brackets = brackets .. ' (РККА)'
	else
		report.gene = owngene
	end

	b, quotes = string.match( a, '^(.+)( ' .. translation[3] .. '.+' .. translation[4] .. ')$' )
	if b then
		a = b
	else
		quotes = ''
	end

	numb, b = string.match( a, '^(%d+%-?[абв]?) (.+)$' )
	if numb then
		numb = numb .. report.space
		a = b
	end

	-- ИИИ отд. гв. ТТТ: (отд. ТТТ), (ТТТ)
	-- ИИИ отд. ТТТ: (отд. ТТТ), (ТТТ)
	-- ИИИ гв. ТТТ: (ТТТ)
	-- ИИИ ТТТ: (ИИИ ТТТ), (ТТТ)


--	name, otd, gv, b = string.match( a, '^(.*)(отд%. )(гв%. )(.+)$' )
	name, otd, gv, b = string.match( a, '^(.*)(' .. translation[1] .. ' )(' .. translation[2] .. ' )(.+)$' )
	if name then
		abbr = acheck( otd .. b, plural )
		if abbr then
			return ( numb or '' ) .. name .. gv .. abbr .. quotes .. brackets
		end
		abbr = acheck( b, plural )
		if abbr then
			return ( numb or '' ) .. name .. otd .. gv .. abbr .. quotes .. brackets
		end
		return str
	end

	name, otd, b = string.match( a, '^(.*)(' .. translation[1] .. ' )(.+)$' )
	if name then
		abbr = acheck( otd .. b, plural )
		if abbr then
			return ( numb or '' ) .. name .. abbr .. quotes .. brackets
		end
		abbr = acheck( b, plural )
		if abbr then
			return ( numb or '' ) .. name .. otd .. abbr .. quotes .. brackets
		end
		return str
	end

	name, gv, b = string.match( a, '^(.*)(' .. translation[2] .. ' )(.+)$' )
	if name then
		abbr = acheck( b, plural )
		if abbr then
			return ( numb or '' ) .. name .. gv .. abbr .. quotes .. brackets
		end
		return str
	end

	abbr = acheck( a, plural )
	if abbr then
		return ( numb or '' ) .. abbr .. quotes .. brackets
	end

	name, b = string.match( a, '^([^ ]+ )(.+)$' )
	if name then
		abbr = acheck( b, plural )
		if abbr then
			return ( numb or '' ) .. name .. abbr .. quotes .. brackets
		end
	end

	return str
end

function report.outPart( showMode, link, unit, addendum, reference, inFormation, hq )
	-- showMode = false/nil не показывать, 1 кратко, 2 полностью; string — текст, показываемый вместо названия юнита (для буферизации)
	-- link = true — превращать в ссылку (игнор при mode=false/nil)
	local res = {}
	if link and showMode then
		table.insert( res, '[[' .. unit )
		if showMode == 1 then
			table.insert( res, '|' .. report.shorter( unit ) )
		elseif showMode == 2 then
			local woBrackets = string.gsub( unit, ' %b()', function( a )
					if type( knownBrackets[a] ) ~= 'string' then
						return ''
					end
				end )
			table.insert( res, '|' .. woBrackets )
		elseif type( showMode ) == 'string' then
			table.insert( res, '|' .. showMode )
		end
		table.insert( res, ']]' )
	elseif showMode == 2 then
			local woBrackets = string.gsub( unit, ' %b()', function( a )
					if type( knownBrackets[a] ) ~= 'string' then
						return ''
					end
				end )
		table.insert( res, woBrackets )
	elseif showMode == 1 then
		table.insert( res, report.shorter( unit ) )
	end
	if reference ~= '' then
		table.insert( res, ref.use( reference, report.pageMode ) )
	end
	if type( showMode ) ~= 'string' then
		if ( hq or '' ) ~= '' then
			table.insert( res, ' (<span title="' .. translation[5] .. '">&empty;</span>)' )
		end
		if addendum ~= '' then
			table.insert( res, ' <i>(' .. addendum .. ')</i>' )
		end
		if inFormation ~= '' then
			formation = formation or mw.loadData( translation[16] )
			table.insert( res, ' — <i>' .. formation.FUP[tonumber( inFormation )] .. '</i>')
		end
	end
	return table.concat( res )
end

function report.outEl( tab, n, showMode, link, compact )
	local res = ''
	local unit = tab['id'..n]
	if unit ~= '' then
		if unit == translation[6] then
			return nil
		elseif unit == translation[7] then
			if string.match( tab['id'..(n -1)], translation[8] ) or string.match( tab['id'..(n -1)], translation[17] ) then
				return nil
			else
				return '<i>(' .. translation[9] .. ')</i>'
			end
		elseif unit == translation[10] then
			if string.match( tab['id'..(n -1)], translation[11] ) then
				res = '<i>(' .. translation[12] .. ')</i> / '
			end
			unit = translation[13]
		elseif unit == translation[14] then
			if string.match( tab['id'..(n -1)], translation[15] ) then
				res = '<i>(' .. translation[6] .. ')</i> / '
			end
			unit = translation[13]
		end
		if compact then
			return report.toBuffer( tab, n )
		end
		res = res .. report.outPart( showMode, link, unit, tab['add'..n], tab['ref'..n], tab['form'..n], tab['hq'..n] )
		if tab['s_id'..n] ~= '' then
			res = res .. ' [<i></i>' .. report.outPart( showMode, true, tab['s_id'..n], tab['s_add'..n], tab['s_ref'..n], '', '' ) .. ']'
		end
		return res
	end
end

function report.toBuffer( tab, n )
	local unit = tab['id'..n]
	unit = string.match( unit, '^(.-) %(.+%)$' ) or unit
	local x, u = string.match( unit, '^([^ ]+) (.+)$' )
	local res
	if not x then
		x = unit
		u = ''
	end
--	assert( x, unit )
	if bufferCommon and
	( u ~= bufferCommon or tab['add'..n] ~= bufferCommonAdd
		or tab['form'..n] ~= bufferCommonForm  or tab['s_id'..n] ~= bufferCommonStruct
		or bufferCommonGene ~= report.gene or tab['hq'..n] ~= bufferCommonHq ) then
		res = report.popBuffer()
	end
	if not bufferCommon then
--		bufferTab = tab
		bufferCommon = u
		bufferCommonAdd = tab['add'..n]
		bufferCommonForm = tab['form'..n]
		bufferCommonStruct = tab['s_id'..n]
		bufferCommonHq = tab['hq'..n]
		bufferCommonN = n
		bufferCommonGene = report.gene
	end
	table.insert( buffer, { n, x, tab } )
	return res
end

function report.popBuffer()
	if bufferCommon then
		local savedGene = report.gene
		report.gene = bufferCommonGene
		if #buffer == 1 then
			local n, utab = buffer[1][1], buffer[1][3]
			buffer = {}
			bufferCommon = nil
			local res = report.outEl( utab, n, 1, true )
			report.gene = savedGene
			return res
		end
		local res = {}
		for _, el in ipairs( buffer ) do
			local n, unumb, utab = el[1], el[2], el[3]
			table.insert( res, report.outPart( unumb, true, utab['id'..n], bufferCommonAdd, utab['ref'..n], bufferCommonForm, bufferCommonHq ) )
			-- в реальности add, form, hq тут игнорируются
		end
		res = { table.concat( res, ', ' ) .. report.space .. report.shorter( bufferCommon, true ) }
		if ( bufferCommonHq or '' ) ~= '' then
			table.insert( res, ' (<span title="Управление без войск">&empty;</span>)' )
		end
		if bufferCommonAdd ~= '' then
			table.insert( res, '<i>(' .. bufferCommonAdd .. ')</i>' )
		end
		if bufferCommonForm ~= '' then
			formation = formation or mw.loadData( translation[16] )
			table.insert( res, '— <i>' .. formation.FUP[tonumber( bufferCommonForm )] .. '</i>' )
		end
		local btab = buffer[1][3]
		if bufferCommonStruct ~= '' then
			table.insert( res, '[<i></i>' .. report.outPart( 1, true, bufferCommonStruct, btab['s_add'..bufferCommonN], btab['s_ref'..bufferCommonN], '' ) .. ']' )
		end
		buffer = {}
		bufferCommon = nil
		report.gene = savedGene
		return table.concat( res, ' ' )
	else
		return nil
	end
end


function report.printDate( str )
	if ( str or '' ) ~= '' then
		return '<span class=date-field>'
		.. string.sub( str, 9, 10 ) .. '.' .. string.sub( str, 6, 7 ) .. '.'
		.. string.sub( str, 1, 4 ) .. '</span>'
	end
	return '<span class=date-field>&nbsp;</span>'
end

function report.printDateLink( page, bookpage, text )
	local basepage, date, part
	if ( bookpage or '' ) == '' then
		bookpage = ''
	else
		bookpage = '#p' .. bookpage
	end
	if page then
		basepage, date, part = string.match( page, '^(.+ (%d%d%.%d%d%.%d%d%d%d))/(%d)$' )
		assert( basepage )
		date = '[[' .. basepage .. bookpage .. '|' .. ( text or date ) .. ']]'
	else
		date = '&nbsp;'
		part = ''
	end
	return '<span class="oobdate date-field" data-part="' .. part .. '">'
		.. date .. '</span>'
end

function report.printDateWithLink( row )
	local basepage, date, part, page, bookpage
	if ( row.bookpage or '' ) == '' then
		bookpage = ''
	else
		bookpage = '#p' .. row.bookpage
	end
	page = row.page
	if page then
		basepage, part = string.match( page, '^(.+)/(%d)$' )
		assert( basepage )
		if english then
			date = row.date
		else
			date = string.sub( row.date, 9, 10 ) .. '.' .. string.sub( row.date, 6, 7 ) .. '.'
				.. string.sub( row.date, 1, 4 )
		end
		date = '[[' .. basepage .. bookpage .. '|' .. date .. ']]'
	else
		date = '&nbsp;'
		part = ''
	end
	return '<span class="oobdate date-field" data-part="' .. part .. '">'
		.. date .. '</span>'
end


return report