Модуль:Unit
Материал из Указатель частей и соединений РККА 1941-1945
Версия от 11:28, 13 января 2020; Строк (обсуждение | вклад)
Для документации этого модуля может быть создана страница Модуль:Unit/doc
local p = {} local global = mw.ext.luaglobal local tools = require( 'Module:Tools' ) local ref = require( 'Module:Ref' ) local cargo = mw.ext.cargo local REF_ORIG = 'o' local REF_MY = 'm' -- !, :{Формирование указано в таблице на текущую дату дважды. Это может быть связано с процессом переподчинения.}, -- !, :{В оригинале указан * (он же указан в составе *). В составе 3 мк был 1 мцп, см. [[вп:Механизированный корпус РККА]].}, -- !, :Неверная аббревиатура в оригинале, -- , !, :Неверная аббревиатура в оригинале -- | * /corp/В оригинале отсутствуют указания на точку окончания перечисления соединений и частей, входящих в состав корпуса; при подготовке материала для размещения на сайте могла быть допущена ошибка. --[[ ИЗ СОСТАВА Формы 1) 310 сп (140 сд) == ф | 310 | сп | /( | 140 сд | ) | == на основе слова «/(» понимаем, что следующий элемент надо не в стек запихивать, а делать запись в особой табличке «обособленные дети» 2) 140 сд (без 310 сп) == это просто комментарий 3) 1/415 гап == заносим обычным образом в основную таблицу с таким номером (но ссылка должна быть на 415 гап) 4) 190 гап (один дивизион из) 5) 190 гап (без одного дивизиона) 6) 4 акп: ... --]] --[[ pageunits - это название — разнописание основного - это название — общее название для нескольких формирований - это название индивидуализирует формирование - это набор преобразований одного формирования (вопрос: при нынешней схеме мы не можем в базе по имени найти разнописания) Осталось сделать: 2) разобраться с управлениями/полевыми управлениями 9) разноформатные табы в разных разделах 12) все доп.аргументы (сноски, текст, и проч. для ПОДЧИНЕНИЯ) — невозможно сделать нормально, ему не соответствует юнит 13) проверить аргумент текст для АРМИЯ 18) ENG 19) убрать что-нибудь в php 20) разобраться с недействующей частью ЗакФ 21) группировки: Требуется группировать (а) тезкт. в зависимости от существования главного тезки, страница с перечнем тезок именуется либо |«ХХХХ (*)»|, либо |«ХХХХ»| (б) поколения/преобразования/переименования. Эта страница является парной к полному имени (включающему скобки). Поэтому тут логично использовать не скобки, а подстраницу. |«YYYY/преобразования»|. Или так |«YYYY — преобразования»|. И то, и другое ищем по базе, а не через _pageexists_ 23) 2 ПрибФ 12.1944 — много бригад из состава 6 гв. адп!!! 24) Дооформить «восстановленный БС» — примечания и проч. 25) Перейти на единые процедуры для примечаний 26) решить, что делать с правками (пометки у зачеркиваний или примечания) 27) переносить в базу флаг «управление» + 1) из состава + 3) примечания (сделать и расставить) + 4) наглядные исправления опечаток + 5) иностранные формирования «~/» + 5а) групповая добавка ВП для польских армий + 5б) страна РККА внутри иностранной группы (для нашего соединения, подчиненного иностранцам) + 6) хвост для различения омонимов + 7) ~ххх при списке номеров (брмп балтфлота 01.1942, внутренняя оборона Ленинграла 01-07.1943, иностранцы) + 8) шаблон:Раздел ПВО + 10) Превращать «гв. отд.» в «отд. гв.». Делать после стыковки с номером (на случай, если гв. — часть номера)! + 11) Dry для {{армия}} и проч. + 14) собственная система примечаний (автоматическое определение дублей) на каждую группу комментариев: счетчик (он же признак, что комментарии прочитаны) URefCount(O/M), сам массив комментариев URef(O/M), флаг записи, Номер части URefPart (o/m) структура массива: [текст комментария]={номер, число обратных ссылок} + 15) группировка иностранных формирований в разделе «Состав» + 16) похожие наименования + 17) «~(...)» — эквивалент «/(...)» плюс добавление в название + 22) сверхбольшие составы (2 УкрФ, ЗапФ) --]] local data = mw.loadData( 'Module:Data' ) local formation -- = mw.loadData( 'Module:Formation' ) переставил загрузку к месту использования local uStack, modStack, uPorno --, uDry local lastU, bsDate, uTab, uDBmode, uDBcount, uPage local inFormation, pageId, lastForeign, DB -- живут в пределах одного шаблона --- local uRefPart, uRefCount, uRef, modRef = {}, {}, {}, {} modRef = modRef or {} local function fStart() uStack = global.get( 'UStack' ) -- сохраняется по modStack lastU = global.get( 'LastU' ) or '' -- сохраняется всегда uDBcount = global.get( 'UDBcount' ) or 0 uPorno = global.get( 'UPorno' ) or 0 -- сохраняется всегда (и всегда соответствует lastU, если оно установлено! uTab = global.get( 'UTab' ) -- сохраняется вручную uPage = global.get( 'UPage' ) -- сохраняется вручную DB = {} end local function flashDB() local res = '' if #DB then local frame = mw.getCurrentFrame() for _, u in ipairs( DB ) do if uDBmode == 2 then global.add( 'RKKA-log', u ) else res = res .. frame:expandTemplate{ title = 'Таблица формирований', args = u } end end DB = {} end return res end local function fReturn( text ) if modStack then global.set( 'UStack', uStack ) modStack = nil end global.set( 'LastU', lastU ) global.set( 'UPorno', uPorno ) global.set( 'UDBcount', uDBcount ) --- return text text = text .. flashDB() if next( modRef ) then return ref.refReturn( text ) else return text end end local function closeTabs() -- завершаем текущий таб. Отсутствующие табы дозаполнять не надо if uTab then uTab = nil global.set( 'UTab', nil ) return p._closeTab() .. '</div>' -- tab, tab-wrap и row-wrap end return '' end function p.Part( frame ) local args = tools.checkargs( frame:getParent().args, { '', } ) local x = tonumber( args[1] ) assert ( x and x >= 0 and x <= 9, 'Недопустимый номер части таблицы боевого состава' ) global.set( 'UPartBS', x ) local tit = mw.title.getCurrentTitle().fullText .. '/' .. x -- <div class="rkka-editor pull-right">[{{fullurl:{{FULLPAGENAME}}/{{{1|}}}|action=edit}} <i class="glyphicon glyphicon-pencil"></i>]</div>{{ {{FULLPAGENAME}}/{{{1|x}}} }} return '<div class="rkka-editor pull-right">[' .. tostring( mw.uri.fullUrl( tit, { action = 'edit' } ) ) .. '<i class="glyphicon glyphicon-pencil"></i>]</div>' .. frame:expandTemplate{ title = tit } end function p.Write( frame ) local args = tools.checkargs( frame:getParent().args, { '', } ) uDBmode = global.get( 'UDBmode' ) local mytitle = mw.title.getCurrentTitle() local stamp, part = string.match( mytitle.text, ' (%d%d%.%d%d%.%d%d%d%d)/(.)$' ) local locked = ( mw.title.new( 'РККА:Блокировка БД' ).id or 0 ) ~= 0 --[[ заменяем uDry на uDBmode: nil — никакой записи, 1 — блокировка страницей-семафором, 2 — протокол, у нас есть типы страниц с шаблоном «Запись»: «пишущие части», «тестовые», «публичные» и страница-семафор Шаблон Запись (начало): - /1 + семафор — nil - /1 без семафора — 1 - /t - 2 - основная — 3 на основных мы считаем в UDBcount число записей в базу --]] if args[1] == 'конец' then if uDBmode == 1 then return frame:expandTemplate{ title = 'Таблица формирований', args = { unit = 'Запись в БД', tab = 'финиш', } } elseif uDBmode == 2 then -- return mw.dumpObject( global.get( 'RKKA-log' ) ) local log, res = global.get( 'RKKA-log' ), {} for _, t in ipairs( log ) do local row = {} table.insert( row, t.unitId or '—' ) table.insert( row, '[[' .. ( t.unit or '—' ) .. ']]' ) table.insert( row, '<i>' .. ( t.parentId or '—' ) .. '</i>' ) table.insert( row, '<i>[[' .. ( t.parent or '—' ) .. ']]</i>' ) table.insert( row, t.structParentId or '—' ) table.insert( row, t.addendum or '—' ) table.insert( row, t.ref or '—' ) table.insert( row, t.ass or '—' ) table.insert( row, t.tab or '—' ) table.insert( row, t.creating or '—' ) table.insert( res, '<tr><td>' .. table.concat( row, '</td><td>' ) .. '</td></tr>\n' ) end return '<table class="table table-condensed table-hover>' .. '<tr><th>Id</th><th>Unit</th><th>pId</th><th>Parent</th><th>strP</th><th>add</th><th>ref</th><th>Ass</th><th>Tab</th><th>Create</th></tr>\n' .. table.concat( res ) .. '</table>' elseif uDBmode == 3 then -- do return '(' .. ( global.get( 'UPartBS' ) or ' ((?)) ' ) .. ')<br>' end -- local tmp = '/' .. global.get( 'UPartBS' ) -- tmp = mw.title.getCurrentTitle() .. '/' local dbCount = cargo.query( 'units', 'COUNT(_pageID)=X', { where = '_pageTitle="' .. mw.title.getCurrentTitle().text .. '/' .. global.get( 'UPartBS' ) .. '"' } ) local luaCount = global.get( 'UDBcount' ) frame:expandTemplate{ title = 'Таблица контроля БД', args = { pagel = luaCount, basel = dbCount[1].X - 2, } } if luaCount ~= dbCount[1].X - 2 then return '<p class="rkka-editor error">Ошибка! В базе ' .. ( dbCount[1].X - 2 ) .. ' записей вместо ' .. luaCount .. '</p>' else -- return '<p class="rkka-editor">В базе ' .. dbCount[1].X .. ' записей</p>' end global.set( 'UDBcount', 1 ) --09022019 else return end end local txt = '' if tonumber( part ) then if locked then uDBmode = nil txt = '<p class=error>Запись в базу данных [[РККА:Блокировка БД|<span class=error>заблокирована!</span>]]</p>' else uDBmode = 1 frame:expandTemplate{ title = 'Таблица формирований', args = { unit = 'Запись в БД', tab = 'старт', } } end txt = txt .. '[[Категория:Боевой состав|' .. string.sub( stamp, 7, 10 ) .. string.sub( stamp, 4, 5 ) .. string.sub( stamp, 1, 2 ) .. part .. ']]' elseif part then uDBmode = 2 else uDBmode = 3 global.set( 'UDBcount', 0 ) --09022019 end global.set( 'UDBmode', uDBmode ) return txt end local function writeDB( frame, args ) if uDBmode == 1 then -- return frame:expandTemplate{ title = 'Таблица формирований', args = args } table.insert( DB, args ) elseif uDBmode == 2 then -- global.add( 'RKKA-log', args ) table.insert( DB, args ) elseif uDBmode == 3 then uDBcount = uDBcount + 1 end return '' end function p.BS( frame ) local args = tools.checkargs( frame:getParent().args, { '', '', ['текст'] = '' } ) return p._bs( args, frame ) end p['Боевой состав'] = p.BS function p._bs( args, frame ) local bsDateArg = args[1] if bsDateArg == 'конец' or bsDateArg == 'разрыв' and mw.title.getCurrentTitle().subpageText ~= mw.title.getCurrentTitle().text then fStart() ref.refStart() local x = closeTabs() -- .. '<br>' -- x = x .. '<hr style="margin:0;border:1px solid #aaa">' -- плохо из-за первого раздела ПВО global.set( 'BSDate', nil ) x = x .. ref.refOut() return fReturn( x ) end if bsDateArg == '' then local x = mw.title.getCurrentTitle().text bsDateArg = string.match( x, '(194%d%-%d%d%-%d%d)' ) if not bsDateArg then bsDateArg = string.match( x, '(%d%d%.%d%d%.194%d)' ) if bsDateArg then bsDateArg = string.sub( bsDateArg, 7, 10 ) .. '-' .. string.sub( bsDateArg, 4, 5 ) .. '-' .. string.sub( bsDateArg, 1, 2 ) end end end if ( bsDateArg or '' ) == '' then error( '<p class=error>Непонятна дата</p>' ) end bsDate = global.get( 'BSDate' ) if bsDate then -- это разрыв и в конце прежнего файла, и в начале нового -- error( '<p class=error>Не закрыт предыдущий раздел!</p>' ) if bsDateArg ~= 'разрыв' then global.set( 'UDBcount', 1 ) end return '<i></i>' end bsDate, lastU = bsDateArg, args[2] local title = args[2] local descr = data.Tabs[lastU] if not descr then error( '<p class=error>Несуществующий раздел</p>' ) end lastU = descr.unit or title global.set( 'BSDate', bsDate ) global.set( 'UStack', { { war = descr.war, unit = title, ass = 1, porno = descr.code } } ) local db = '' if descr.code ~= '' then DB = DB or {} uDBmode = global.get( 'UDBmode' ) uDBcount = global.get( 'UDBcount' ) or 0 db = writeDB( frame, { fix = bsDate, unit = lastU, -- parent = nil, unitId = mw.title.getCurrentTitle().id .. ':' .. descr.code, -- parentId = nil, -- structParentId = structParent, -- creating = inFormation, war = descr.war, -- ass = assLvl, -- ref = refer, -- addendum = addendum, -- partial = nil, } ) flashDB() global.set( 'UDBcount', uDBcount ) end local level = descr.level or 2 return '<h' .. level .. '>' .. title -- .. ' <small>по состоянию на ' .. string.sub( bsDate, 9, 10 ) .. '.' -- .. string.sub( bsDate, 6, 7 ) .. '.' .. string.sub( bsDate, 1, 4 ) -- .. '</small>' .. '</h' .. level .. '>' .. db end function p.Open( frame ) local args = tools.checkargs( frame:getParent().args, { '' } ) fStart() return fReturn( p._openLevel( args[1] ) ) end p['('] = p.Open function p._openLevel( arg, assLvl ) table.insert( uStack, { unit = lastU, war = uStack[#uStack].war, ass = assLvl, porno = uPorno, gene = lastForeign or uStack[#uStack].gene } ) modStack = true lastU = nil local out = '(' if arg == '-' then out = '' end return out end function p.Close( frame ) local args = tools.checkargs( frame:getParent().args, { '' } ) fStart() return fReturn( p._closeLevel( args[1] ) ) end p[')'] = p.Close function p._closeLevel( arg ) table.remove( uStack ) modStack = true lastU = nil if arg == '-' then return '' end return ')' end function p.F( frame ) local args = tools.checkargs( frame:getParent().args, { ['текст'] = true, f = true, }, true ) -- TODO Проверка на ошибки fStart() bsDate = global.get( 'BSDate' ) -- uDry = global.get( 'UNoDry' ) -- if uDry == true then -- uDry = nil -- elseif uDry ~= 'protocol' then -- uDry = '' -- end uDBmode = global.get( 'UDBmode' ) -- uDBcount = global.get( 'UDBcount' ) pageId = mw.title.getCurrentTitle().id local res = {} local empty = global.get( 'UTabEmpty' ) if empty then res = { '<p>' } global.set( 'UTabEmpty', nil ) end local modeRevers local n1, n2 local corrForReversText, corrForReversDB local function pop( revStruct ) if n2 then table.insert( res, p._f( frame, args, n1, n2, nil, revStruct, modeRevers == 3 ) ) n2 = nil end end for i, x in ipairs( args ) do if x == '(' then pop() table.insert( res, ' ' .. p._openLevel( '' ) ) elseif x == ')' then if modeRevers == 2 then modeRevers = nil pop( 2 ) table.insert( res, ']' ) elseif modeRevers == 3 then modeRevers = nil pop( 2 ) -- global.add( 'DEBUGLOG', corrForReversDB .. ': ' .. type( DB[corrForReversDB] ) .. ', ' .. type( DB[corrForReversDB].unit ) ) -- global.add( 'DEBUGLOG', #DB .. ': ' .. type( DB[#DB] ) .. ', ' .. type( DB[#DB].unit ) ) for iDB = corrForReversDB+1, #DB-1 do DB[iDB].unit = string.gsub( DB[iDB].unit, '%(%)', '(' .. DB[#DB].unit .. ')' ) end res[corrForReversText+1] = string.gsub( res[corrForReversText+1], '%(%)', '(' .. DB[#DB].unit .. ')' ) table.insert( res, ']' ) else pop() if uStack[#uStack].ass then table.insert( res, '<br><span class=error>ОШИБКА! Лишняя закрывающая скобка записи о корпусе[[Категория:Ошибки скобок]]</span><br>' ) else table.insert( res, p._closeLevel( '' ) ) end end elseif x == ',' or x == ';' or x == '.' then if modeRevers then table.insert( res, '<br><span class=error>ОШИБКА! Ссылка на вышестоящее формирование не завершилась скобкой[[Категория:Ошибки скобок]]</span><br>' ) end pop() table.insert( res, x .. ' ' ) elseif x == '/(' then modeRevers = 2 -- обычный modeRevers pop( 1 ) table.insert( res, ' [<i></i>' ) elseif x == '~(' then modeRevers = 3 -- modeRevers с добавкой в названия юнитов corrForReversDB = #DB corrForReversText = #res pop( 1 ) table.insert( res, ' [<i></i>' ) elseif x == '\\(' then table.insert( res, ' [<i></i>' ) pop( 2 ) table.insert( res, '] (' ) p._openLevel( '-' ) uStack[#uStack].struct = true elseif string.sub( x, 1, 1 ) == '/' then pop() if not empty then table.insert( res, '<br> ' ) end formation = formation or mw.loadData( 'Module:Formation' ) inFormation = formation.FUPcode[string.sub( x, 2, -1 )] if inFormation ~= '' then table.insert( res, '<i>На ' .. formation.FUP[inFormation] .. ': </i>' ) end elseif n2 then n2 = i else n1 = i n2 = i end empty = false end pop() -- global.set( 'LastU', lastU ) -- fReturn сохранит return fReturn( table.concat( res ) ) end p['Ф'] = p.F local function gvotd( str ) return string.gsub( str, 'гв%. отд%.', 'отд. гв.', 1 ) end local function id( num ) if tonumber( num ) then return pageId .. ':' .. string.sub( '00000' .. num, -5, -1 ) end return pageId .. ':' .. num end function p._f( frame, args, start, stop, assInfo, revStruct, addStruct ) local assLvl, assTab, assPage if assInfo then assLvl, assTab = assInfo[1], assInfo[2] end assPage = uPage -- assLvl нужен для восстановления структуры на страницах формирований при извлечении из базы -- revStruct ----- revStruct = 1 — полк в формате «полк (дивизия)». В этом случае в качестве structParent мы занесем porno+1 ----- revStruct = 2 — признак собственно structParent. В этом случае в качестве Parent мы занесем «СТРУКТУРА». И это всегда уникальное/единичное обозначение ----- addStruct = true — для полка в формате «полк (дивизия)» — к полку добавить «()», чтобы потом заменить на «(дивизия)» local err = {} -- массив сообщений об ошибках local parent, structParent = uStack[#uStack] if parent.struct then parent, structParent = uStack[#uStack-1], parent if revStruct == 1 then table.insert( 'Слуга двух господ' ) end end if addStruct then addStruct = ' ()' else addStruct = '' end local numbers = args[start] local abbr = args[start+1] -- это то, что мы будем расшифровывать local prabbr = abbr -- так должно выглядеть на печати по умолчанию local refer, addendum, onlyPU, post, hidden, foreign -- *xxx, +xxx, --, ++, ~xxx /////create, if args['для'] then refer = { '-' .. args['для'] } elseif uStack[#uStack].forfor and not uStack[#uStack].forTop then refer = { '-' .. uStack[#uStack].forfor } else refer = {} end local arg for i = stop, start+1, -1 do arg = args[i] if arg == '--' then onlyPU = true else local t = string.sub( arg, 1, 1 ) if t == '*' then table.insert( refer, mw.text.trim( string.sub( arg, 2, -1 ) ) ) elseif t == '+' then addendum = mw.text.trim( string.sub( arg, 2, -1 ) ) elseif t == '~' then local u = string.sub( arg, 1, 2 ) if u == '~+' then post = ' ' .. mw.text.trim( string.sub( arg, 3, -1 ) ) elseif string.sub( arg, 1, 2 ) == '~/' then u = data.Foreign[mw.text.trim( string.sub( arg, 3, -1 ) )] if u then foreign = ' (' .. u .. ')' else table.insert( err, 'Неизвестное обозначение иностранного формирования' ) end else hidden = ' (' .. mw.text.trim( string.sub( arg, 2, -1 ) ) .. ')' end else arg = i break end end arg = start end if #refer == 0 then refer = nil else refer = table.concat( refer, '$' ) end lastForeign = foreign or uStack[#uStack].gene -- foreign = lastForeign stop = arg or stop -- мы не знаем количество элементов списка, для уникального формирования он может быть и пустым, и непустым (если там есть модификатор). if start == stop then abbr = numbers -- это то, что мы будем расшифровывать prabbr = numbers -- так должно выглядеть на печати по умолчанию numbers = {} -- номерной части нет else if stop ~= start+1 then table.insert( err, 'Лишние сегменты в описании формирования' ) stop = start+1 end local hiddencomments = {} numbers = string.gsub( numbers, '%{([^}]+)%}', function ( a ) table.insert( hiddencomments, a ) return '{' .. #hiddencomments .. '}' end ) numbers = mw.text.split( numbers, '[%s]*,[%s]*' ) for i, u in ipairs( numbers ) do numbers[i] = string.gsub( u, '%{(%d+)%}', function ( a ) return hiddencomments[tonumber( a )] end ) end if #numbers ~= 1 and numbers[#numbers] == '' then -- удаляем последнюю запятую, надо про это не забыть: каким-то маркерам это может быть важно table.remove( numbers ) end end local descr = data.Units[abbr] local otd = '' local changed repeat changed = false if type( descr ) == 'string' then abbr = descr descr = data.Units[abbr] changed = true end if not descr then if mw.ustring.sub( abbr, 1, 5 ) == 'отд. ' then otd = 'отд. ' abbr = mw.ustring.sub( abbr, 6, -1 ) descr = data.Units[abbr] changed = true end if not descr and mw.ustring.sub( abbr, 1, 4 ) == 'гв. ' then otd = otd .. 'гв. ' abbr = mw.ustring.sub( abbr, 5, -1 ) descr = data.Units[abbr] changed = true end end if descr and descr.alt then if descr.alt[uTab] then abbr = descr.alt[uTab] descr = data.Units[abbr] changed = true elseif not descr.alt[1] then table.insert( err, 'Неоднозначное обозначение формирования «' .. abbr .. '» в колонке «' .. uTab .. '»' ) -- (' .. log .. ') descr = { class = 'unknown' } changed = false end end until not changed local tabf = {} local modif, marking, striking, refInList, oncehidden for _, numb in ipairs( numbers ) do if modif then -- маркеры ---- !, зачеркнутое:комментарий, -- включение зачеркнутого текста с возможным комментарием ---- !, !, -- выделение ссылки ---- !, :примечание, — только для списков. На будущее надо предусмотреть «*{ примечание с запятыми }» ---- !, ~добавка (аналог ~+) if numb == '!' then marking = true else if not hidden and string.sub( numb, 1, 1 ) == '~' then oncehidden = ' (' .. mw.text.trim( string.sub( numb, 2, -1 ) ) .. ')' else local colon = string.find( numb, ':', 1, true ) if colon == 1 then refInList = string.sub( numb, 2, -1 ) else if colon then numb, colon = string.sub( numb, 1, colon-1 ), string.sub( numb, colon+1, -1 ) else colon = '(текст исключен)' end striking = '<s><span class=striked title="' .. colon .. '"> ' .. numb .. ' </span></s> ' end end end modif = nil elseif numb == '!' then modif = true else local refDB if refInList and refer then refDB = refInList .. '$' .. refer else refDB = refInList or refer end table.insert( tabf, { striked = striking, marked = marking, text = numb, refPrint = refInList, refDB = refDB, ownhidden = oncehidden } ) marking, striking, refInList, oncehidden = nil, nil, nil, nil end end if modif then table.insert( err, 'Список закончился модификатором' ) end if not descr then table.insert( err, 'Неизвестное обозначение формирования «' .. abbr .. '»' ) descr = { class = 'unknown' } elseif descr.uniq and #tabf ~= 0 then table.insert( err, 'Указан номер уникального формирования' ) end local res if #tabf == 0 then if not descr.uniq then table.insert( err, 'Отсутствует номер регулярного формирования' ) end local text if args.f then text = descr[args.f] end text = args['текст'] or ( otd .. ( text or prabbr ) .. ( post or '' ) .. ( foreign or '' ) ) if marking then text = '<u>' .. text .. '</u>' end lastU = otd .. ( descr.n or abbr ) .. ( post or '' ) .. ( hidden or '' ) .. addStruct .. ( lastForeign or '' ) res = ( striking or '' ) .. '[[' .. lastU if text ~= lastU then res = res .. '|' .. text end uPorno = uPorno + 1 if revStruct == 1 then structParent = id( uPorno + 1 ) elseif structParent then structParent = id( structParent.porno ) end if revStruct == 2 then res = res .. ']]' .. writeDB( frame, { fix = bsDate, unit = lastU, parent = parent.unit, unitId = id( uPorno ), parentId = 'структура', structParentId = structParent, creating = inFormation, war = parent.war, ass = assLvl, addendum = addendum, ref = refer, } ) else res = res .. ']]' .. writeDB( frame, { fix = bsDate, unit = lastU, parent = parent.unit, unitId = id( uPorno ), parentId = id( parent.porno ), structParentId = structParent, creating = inFormation, war = parent.war, ass = assLvl, asstab = assTab, page = assPage, ref = refer, addendum = addendum, tab = uTab, hq = onlyPU, } ) end elseif #tabf == 1 then if tabf[1].striked then striking = tabf[1].striked .. ( striking or '' ) end if tabf[1].marked then marking = true end refer = tabf[1].refDB local text if args.f and descr[args.f] then text = otd .. descr[args.f] end text = ( text or prabbr ) .. ( post or '' ) local numbertext = tabf[1].text local slash if numbertext == '-' then if not post then text = text .. ' <span style="letter-spacing:-0.3ex; font-style:italic;"> <sup>б</sup>/<sub>№</sub></span> ' end numbertext = '' else slash = string.find( numbertext, '/', 1, true ) if slash then slash, numbertext = string.sub( numbertext, 1, slash ), string.sub( numbertext, slash+1, -1 ) text = '<span class=nolink>' .. slash .. '</span>' .. numbertext .. ' ' .. text else text = numbertext .. ' ' .. text end numbertext = numbertext .. ' ' end text = text .. ( foreign or '' ) text = args['текст'] or text if marking then text = '<u>' .. text .. '</u>' end lastU = gvotd( numbertext .. otd .. ( descr.n or abbr ) .. ( post or '' ) .. ( hidden or tabf[1].ownhidden or '' ) .. addStruct .. ( lastForeign or '' ) ) res = ( striking or '' ) .. '[[' .. lastU if text ~= lastU then res = res .. '|' .. text end uPorno = uPorno + 1 if revStruct == 1 or slash then structParent = id( uPorno + 1 ) elseif structParent then structParent = id( structParent.porno ) end if slash then uPorno = uPorno + 1 res = res .. ']]' .. writeDB( frame, { fix = bsDate, unit = slash, parent = parent.unit, unitId = id( uPorno - 1 ), parentId = id( parent.porno ), structParentId = structParent, creating = inFormation, war = parent.war, -- ass = 9, -- 11.01.2019 кажется, никому это не нужно ref = tabf[1].refDB, addendum = addendum, tab = uTab, hq = onlyPU, } ) .. writeDB( frame, { fix = bsDate, unit = lastU, parent = parent.unit, unitId = id( uPorno ), parentId = 'структура', -- structParentId = structParent, -- creating = inFormation, -- war = parent.war, -- ass = assLvl, -- ref = refer, -- partial = nil, } ) elseif revStruct == 2 then res = res .. ']]' .. writeDB( frame, { fix = bsDate, unit = lastU, parent = parent.unit, unitId = id( uPorno ), parentId = 'структура', structParentId = structParent, creating = inFormation, war = parent.war, ass = assLvl, asstab = assTab, page = assPage, addendum = addendum, ref = tabf[1].refDB, -- partial = nil, } ) else res = res .. ']]' .. writeDB( frame, { fix = bsDate, unit = lastU, parent = parent.unit, unitId = id( uPorno ), parentId = id( parent.porno ), structParentId = structParent, creating = inFormation, war = parent.war, ass = assLvl, asstab = assTab, page = assPage, addendum = addendum, ref = tabf[1].refDB, tab = uTab, hq = onlyPU, } ) end else local commonU = ' ' .. otd .. ( descr.n or abbr ) .. ( post or '' ) .. ( hidden or '' ) .. addStruct .. ( lastForeign or '' ) if revStruct == 1 then structParent = id( uPorno + #tabf + 1 ) elseif structParent then structParent = id( structParent.porno ) end res = {} for _, f in ipairs( tabf ) do local text = f.text if f.marked then text = '<u>' .. text .. '</u>' end lastU = gvotd( f.text .. commonU .. ( f.ownhidden or '' ) ) local ownref = f.refPrint if ownref then ownref = ref.use( ownref ) else ownref = '' end uPorno = uPorno + 1 table.insert( res, ( f.striked or '' ) .. '[[' .. lastU .. '|' .. text .. ']]' .. ownref .. writeDB( frame, { fix = bsDate, unit = lastU, parent = parent.unit, unitId = id( uPorno ), parentId = id( parent.porno ), structParentId = structParent, creating = inFormation, addendum = addendum, war = parent.war, ass = assLvl, asstab = assTab, page = assPage, ref = f.refDB, tab = uTab, hq = onlyPU, } ) ) end local text = args['текст'] if text then if text == '-' then text = '' else text = ' ' .. text end if striking or marking then table.insert( 'Модификатор предопределенного текста' ) end else if args.f and descr[args.f] then text = otd .. descr[args.f] end text = ( text or prabbr ) .. ( post or '' ) .. ( foreign or '' ) if marking then text = '<u>' .. text .. '</u>' end text = ' ' .. ( striking or '' ) .. text end res = table.concat( res, ', ' ) .. text end if refer then res = res .. ref.use( refer ) end if addendum then res = res .. ' <i>(' .. addendum .. ')</i>' end if onlyPU then res = res .. ' <i>(управление)</i>' end if #err ~= 0 then err = '<br><span class=error>ОШИБКА! ' .. table.concat( err, '<br>' ) .. '</span>[[Категория:Ошибки в указании формирования]]<br>' else err = '' end return res .. err end local function closeAss( lvl ) -- закрыть все этажи, включая lvl local res = {} -- мы должны были предварительно сходить на closeTabs if not uStack[#uStack].ass then error( 'Не закрыты Табы!!! ' ) end local n = 0 for i = #uStack, 1, -1 do if uStack[i].ass < lvl then n = i break end end for _ = 1, #uStack-n do p._closeLevel( '-' ) end return table.concat( res ) end local function buildChain() local chain = '' for i = #uStack, 2, -1 do chain = chain .. ' / [[' .. uStack[i].unit .. ']]' end return chain end function p.Assoc( frame ) local args = tools.checkargs( frame:getParent().args, { '', ['таб'] = true, ['для'] = true, }, true ) -- TODO Проверка на ошибки fStart() bsDate = global.get( 'BSDate' ) -- uDry = global.get( 'UNoDry' ) -- if uDry == true then -- uDry = nil -- elseif uDry ~= 'protocol' then -- uDry = '' -- end uDBmode = global.get( 'UDBmode' ) pageId = mw.title.getCurrentTitle().id local ass = mw.text.trim( mw.ustring.lower( frame.args[1] ) ) local assLvl = data.Assocs[ass] if not assLvl then error( 'Неизвестный уровень группировки ' .. ass ) end -- завершение ранее открытых tab local tab = closeTabs() -- завершение открытых уровней, более мелких или равных нашему local resAss = closeAss( assLvl ) -- запоминаем самый значимый уровень для раскраски прямого подчинения if not uStack[#uStack].sublevel or uStack[#uStack].sublevel > assLvl then uStack[#uStack].sublevel = assLvl modStack = true end -- строим цепочку подчиненности local chain = buildChain() args.f = 'n' -- полное наименование в именительном падеже local text = p._f( frame, args, 1, #args, { assLvl, args['таб'] } ) p._openLevel( '-', assLvl ) if args['таб'] then global.set( 'UTab', data.Tabs[uStack[1].unit][1] ) if args['для'] then uStack[#uStack].forfor = args['для'] uStack[#uStack].forTop = true modStack = true end -- return fReturn( tab .. resAss -- .. '<div class="bs-raw-wrap"><div class="bs-tab-wrap"><div class="bs-lvl-' -- .. assLvl .. '"><p>' .. text ) return fReturn( tab .. resAss .. '<div class="bs-raw-wrap"><div class="bs-tab-wrap"><div class="bs-ext-assoc-' .. assLvl .. '"><p class="bs-int-assoc">' .. text ) end local page if uPage then page = ' <small>[' .. mw.site.server .. mw.site.scriptPath .. '/images/ExtFiles/' .. string.sub( bsDate, 1, 4 ) .. '.pdf#page=' .. uPage .. ' <i class="fa fa-file-o fa-rotate-90" title="Оригинал, стр. ' .. uPage .. '"></i>]</small>' else page = '' end return fReturn( tab .. resAss .. '<div class="bs-ext-assoc-' .. assLvl .. '"><div class="bs-int-assoc">' .. text .. chain .. page .. '</div></div>' ) end p['Группировка'] = p.Assoc function p.Subord( frame ) local args = tools.checkargs( frame:getParent().args, { '', }, true ) -- TODO Проверка на ошибки fStart() bsDate = global.get( 'BSDate' ) uDBmode = global.get( 'UDBmode' ) local ass = mw.text.trim( mw.ustring.lower( args[1] ) ) local assLvl = data.Assocs[ass] if not assLvl then error( 'Неизвестный уровень группировки ' .. ass ) end -- завершение ранее открытых tab local tab = closeTabs() -- завершение открытых уровней мельче заданного local resAss = closeAss( assLvl+1 ) -- определяем свой уровень assLvl = uStack[#uStack].sublevel or assLvl+1 -- строим цепочку подчиненности local chain = buildChain() if chain == '' then chain = ' / Ставка' end local page if uPage then page = ' <small>[' .. mw.site.server .. mw.site.scriptPath .. '/images/ExtFiles/' .. string.sub( bsDate, 1, 4 ) .. '.pdf#page=' .. uPage .. ' <i class="fa fa-file-o fa-rotate-90" title="Оригинал, стр. ' .. uPage .. '"></i>]</small>' else page = '' end return fReturn( tab .. resAss .. '<div class="bs-ext-assoc-' .. assLvl .. '"><div class="bs-int-assoc">' .. 'Непосредственное подчинение' .. chain .. page .. '</div></div>' ) end p['Подчинение'] = p.Subord function p._closeTab(saveWrap) inFormation = false if not uStack[#uStack].ass then local res = '' while not uStack[#uStack].ass do res = res .. p._closeLevel( '' ) end return res .. '<br><span class=error>ОШИБКА! Отсутствует закрывающая скобка записи о корпусе[[Категория:Ошибки скобок]]</span></p></div></div>' end if saveWrap then return '</p></div>' end return '</p></div></div>' end function p.Row( frame ) local args, hasArg = tools.checkargs( frame:getParent().args, { '', ['для'] = true } ) if not hasArg then error( 'Правильная запись { { Ряд | } }' ) end fStart() if args['для'] then uStack[#uStack].forfor = args['для'] uStack[#uStack].forTop = nil modStack = true if uTab == 'стр' then return fReturn( '' ) end end return fReturn( closeTabs() ) end function p.Tab( frame ) local args = tools.checkargs( frame:getParent().args, { '' } ) fStart() local tabArray = data.Tabs[uStack[1].unit] local prevtab = tabArray[uTab] local newtabname = mw.text.trim( mw.ustring.lower( args[1] ) ) local newtab = tabArray[newtabname] local newtabclass = tabArray[newtabname .. '-class'] local res = {} if not newtab then error( 'Неизвестная колонка ' .. args[1] ) end if prevtab then table.insert( res, p._closeTab( newtab == prevtab ) ) if newtab < prevtab or newtab == prevtab and not newtabclass then error( 'Нарушен порядок колонок (' .. newtab .. ' за ' .. prevtab .. ')' ) end else prevtab = 0 table.insert( res, '<div class="bs-raw-wrap">' ) end for _ = prevtab+1, newtab-1 do table.insert( res, '<div class="bs-tab-wrap hidden-xs"> </div>' ) end if newtab ~= prevtab then table.insert( res, '<div class="bs-tab-wrap">' ) end local tabfor if newtabname == 'для' then tabfor = uStack[#uStack].forfor if tabfor then tabfor = '<p>' .. tabfor end end table.insert( res, '<div class="bs-tab-' .. ( newtabclass or newtab ) .. '">' .. ( tabfor or '' ) ) global.set( 'UTab', newtabname ) global.set( 'UTabEmpty', true ) return fReturn( table.concat( res ) ) end p['Таб'] = p.Tab function p.Dump( frame ) local log = global.get( 'DEBUGLOG' ) if log then global.set( 'DEBUGLOG', nil ) return table.concat( log, '<br>\n' ) end end function p.Total( frame ) local args = tools.checkargs( frame:getParent().args, { true, true, true, true, true, true, true, } ) fStart() local res = { closeTabs() } table.insert( res, '<div class="collapse bs-total"><div class=bs-total-stored>Всего ' .. args[1] .. '</div>' ) table.insert( res, '<div class="bs-raw-wrap">' ) if #args == 7 then args[6] = args[6] .. '</div><div class="bs-total-stored-tab">' .. args[7] args[7] = nil end for i = 2, #args do table.insert( res, '<div class="bs-tab-wrap"><div class="bs-total-stored-tab">' .. args[i] .. '</div></div>' ) end table.insert( res, '</div></div>' ) return fReturn( table.concat( res ) ) end p['Всего'] = p.Total function p.Page( frame ) local page = mw.text.trim( frame:getParent().args[1] ) global.set( 'UPage', page ) return '<span id="p' .. page .. '></span>' end return p