Модуль:Stmm/песочница

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
Документация
-- Этот модуль создаётся для перевода шаблона СтММ на Lua. Название будет определено позже.

local jsontable = mw.loadJsonData('Шаблон:Интерактивная схема Московского метрополитена/песочница/data.json')

local function contains(tbl, x)
    found = false
    for p, v in pairs(tbl) do
        if v == x then 
            found = p 
        end
    end
    return found
end

local function removeparen(text)
    return text:gsub( '^%s*(.+)%s+%b()%s*$', '%1' )
end

local function addquotes(text, icon)
	if (icon) then
		return text
	end
	return '<span class="stmm-quotes">«</span>' .. text .. '<span class="stmm-quotes">»</span>'
end

local function showicon(code, link)
	local iconsize = 15
	if (mw.ustring.find(code, 'D', 1, true)) then
		iconsize = 22
	end
	return '[[File:Moskwa Metro Line ' .. code .. '.svg|' .. iconsize .. 'px|'
		.. 'link=' .. link .. '|' .. removeparen(link) .. ']]'
end

local function splitname(text)
	if (text) then
		local slash = mw.ustring.find(text, '/', 1, true)
		if (slash) then
			return mw.ustring.sub(text, 1, slash - 1), mw.ustring.sub(text, slash + 1)
		end
		return text
	end
end

local function errors(text)
	error(text .. '[[' .. 'Категория:Ошибки в шаблоне метро]]', 0)
end

local function findstation(stationparam)
	local csi, newline, newstation
	local arr = {}
	local allanswers = {}
	local newjson = {}
	for key, value in pairs(jsontable.lines) do
		newline = {article = value.article, train = value.train, stations = {}}
		for key0, value0 in pairs(value.stations or {}) do
			newstation = {article = value0.article, line = value0.line or value.number, rp = removeparen(value0.name or value0.article)}
			if (stationparam == newstation.rp) then
				table.insert(allanswers, {value0.article, newstation.rp, newstation.line, value.article, value.train})
				table.insert(arr, newstation.line)
				if (value0.csi) then
					csi = {value.number, tostring(value0.csi), value.article}
				end
			end
			if (csi and csi[2] == value.number) then
				csi[4] = value.article
			end
			table.insert(newline.stations, newstation)
		end
		if (value.number) then
			table.insert(newjson, newline)
		end
	end
	return arr, allanswers, csi, newjson
end

local function findnextstation(stationparam)
	local rp
	local arr = {}
	local allanswers = {}
	for key, value in pairs(jsontable) do
		for key0, value0 in pairs(value.stations or {}) do
			if (stationparam == value0.rp) then
				table.insert(allanswers, {value0.article, value0.rp, value0.line, value.article, value.train})
				table.insert(arr, value0.line)
			end
		end
	end
	return arr, allanswers
end

local function findstationhint(stationparam)
	local ahint, chint, rp, lowerp
	local lowerstation = mw.ustring.gsub(mw.ustring.lower(stationparam), ' +', ' ')
	for key, value in pairs(jsontable) do
		for key0, value0 in pairs(value.stations or {}) do
			rp = value0.rp
			lowerp = mw.ustring.lower(rp)
			if (lowerp == lowerstation) then
				return rp
			elseif (mw.ustring.find(lowerstation, lowerp, 1, true)
					and (not ahint or (mw.ustring.len(rp) > mw.ustring.len(ahint)))) then
				ahint = rp
			elseif (not ahint and mw.ustring.find(lowerp, lowerstation, 1, true)
					and (not chint or (mw.ustring.len(rp) > mw.ustring.len(chint)))) then
				chint = rp
			end
		end
	end
	return ahint or chint
end

local function formatvariants(vars, cond)
	local err = ', возможные варианты: ' .. mw.ustring.gsub(mw.ustring.gsub(mw.text.jsonEncode(vars), '["%[%]]', ''),',', ', ')
	if (cond) then
		err = err .. ', или используйте параметр «@@» вместо «@» для кроссплатформенных станций'
	end
	return err
end

local function getargs(frame)
	local args = {}
	for p,v in pairs(frame:getParent().args) do
		args[p] = mw.text.trim(v)
	end
	return args
end

function station(frame)
	local startparam = 1
	local iconparam = false
	local interchangeparam = false
	local hyphenparam = false
	local argsnumber = 0
	local stationparam, stationname
	local lineparam = ''
	local icon = ''
	local allanswers, hint
	local articleans, nameans
	local args = getargs(frame)
	local csiparam, csi
	for p, _ in ipairs(args) do
		argsnumber = math.max(argsnumber, p)
	end
	if (args[1] == '@') then
		iconparam = true
		startparam = 2
	elseif (args[1] == '-') then
		iconparam = true
		hyphenparam = true
		startparam = 2
	elseif (args[1] == '&') then
		iconparam = true
		interchangeparam = true
		startparam = 2
	elseif (args[1] == '@@') then
		csiparam = args[2]
		startparam = 2
	end
	if (not csiparam and argsnumber - startparam > 1) then
		errors('Слишком много параметров')
	end
	local unknownpar
	for p, _ in pairs(args) do
		if (not contains({1, 2, 3}, p)) then
			if (csiparam) then
				unknownpar = true
			else
				errors('Неизвестный параметр «' .. p .. '»')
			end
		end
	end
	stationparam, stationname = splitname(args[startparam])
	if (stationparam == '') then
		errors('Пустое название станции')
	end
	if (stationname == '') then
		errors('Пустой текст для показа ссылки')
	end
	if (args[startparam + 1]) then
		lineparam = args[startparam + 1]
	end
	if (csiparam and (args[startparam + 1] or unknownpar)) then
		errors('Параметр «@@» должен использоваться исключительно с названием станции')
	end
	if (not stationparam) then
		errors('Название станции не указано')
	end
	local arr
	arr, allanswers, csi, jsontable = findstation(stationparam)
	if (not csi and csiparam) then
		errors('Параметр «@@» должен использоваться только для кроссплатформенных станций')
	end
	local arrarr, ansarr
	local err = ''
	if (#allanswers == 0) then
		hint = findstationhint(stationparam)
		if (hint) then
			arrarr, ansarr = findnextstation(hint)
			if (#ansarr <= 1) then
				err = '. В номере линии нет необходимости'
			elseif (contains(arrarr, lineparam)) then
				err = ', она может использовать указанный номер линии «' .. lineparam .. '»'
			else
				err = '. Требуется также номер линии' .. formatvariants(arrarr)
			end
			err = ', но, возможно, вы имели в виду «' .. hint .. '»' .. err
		end
		errors('Станция «' .. mw.ustring.gsub(stationparam, '  +', '<много пробелов>') .. '» неизвестна' .. err)
	end
	if (mw.text.jsonEncode(args[startparam + 1]) == '""') then
		if (#allanswers == 1) then
			errors('Номер линии пуст и не требуется')
		elseif (#allanswers > 1) then
			errors('Номер линии пуст' .. formatvariants(arr, csi and iconparam and not hyphenparam))
		end
	end
	if (#allanswers == 1 and lineparam ~= '') then
		errors('Номер линии не требуется: «' .. lineparam .. '»')
	end
	if (not csiparam and ((#allanswers > 1 and not csi) or (#allanswers > 2 and csi)) and lineparam == '') then
		errors('Требуется номер линии' .. formatvariants(arr, csi and iconparam and not hyphenparam))
	end
	local indexans
	if (not csiparam and #allanswers > 1) then
		for key, value in pairs (allanswers) do
			if (value[3] == lineparam) then
				indexans = key
			end
		end
		if (csi and lineparam == '') then
			indexans = 1
		end
	else
		indexans = 1
	end
	if (not indexans) then
		errors('Неверный номер линии: «' .. lineparam .. '»' .. formatvariants(arr, csi and iconparam and not hyphenparam))
	end
	articleans = allanswers[indexans][1]
	nameans = allanswers[indexans][2]
	if (iconparam or csiparam) then
		if (hyphenparam) then
			icon = '&nbsp;—'
		elseif (csi and lineparam == '') then
			icon = icon .. showicon(csi[1], csi[3]) .. showicon(csi[2], csi[4])
		else
			icon = showicon(allanswers[indexans][3], allanswers[indexans][4])
		end
	end
	local ts = ''
	if (iconparam) then
		ts = frame:extensionTag{
				name = 'templatestyles',
				args = { src = 'Шаблон:Stmm/песочница/styles.css' }
			}
	end
	return '<span style="white-space: nowrap">' .. icon .. ' ' .. addquotes('[[' .. articleans .. '|' .. (stationname or nameans)
			.. ']]', not tonumber(mw.ustring.sub(allanswers[indexans][3], 1, 1))
			or allanswers[indexans][5] or iconparam or csiparam) .. '</span>' .. ts
end

function line(frame)
	local args = getargs(frame)
	local ans = ''
	for p, v in pairs(args) do
		if (type(p) ~= 'number') then
			errors('Неизвестный параметр «' .. p .. '»')
		end
		if (v == '') then
			errors('Пустой параметр № ' .. p)
		end
	end
	if (not args[1]) then
		errors('Нет параметров')
	end
	local allines = {}
	local allarticles = {}
	local found
	for _, value in ipairs(jsontable.lines) do
		if (value.number) then
			table.insert(allines, value.number)
			table.insert(allarticles, value.article)
			if (value.altnumber) then
				table.insert(allines, value.altnumber)
				table.insert(allarticles, value.article)
			end
		end
	end
	for _, value in ipairs(args) do
		found = contains(allines, value)
		if (not found) then
			errors('Неизвестная линия «' .. value .. '»')
		end
		ans = ans .. showicon(value, allarticles[found])
	end
	return '<span style="white-space: nowrap">' .. ans .. '&nbsp;</span>'
end

--[==[ Схема шаблона Московские маршруты
?param-text: сплиний(param-1)
 else: ?[[Файл:Logo train transilien.svg|15px|link=param-r/23|бсвл]]
       is-station(param-1): спстанций(param-1)
        else: [[Файл:Moskwa Metro Line param-1 (line?inv:alt)(искл).svg|15px|link=param-l1..сплиний(param-1)|бсвл]]
              ?param-line and ~= 0:
            		<span цвет=param-style..(param-1{12357}?white:black>[[сплиний(param-1)|param-2..сплиний(param-1)]]</span>
               else: ?[[Файл:Moskwa Metro Line param-2/34 alt.svg|15px|link=param-l2/34..сплиний(param-2/34)|бсвл]]
                     ?[[param-c (станция МЦК)|param-c]]
                     ?[[param-m (станция монорельса)|param-m]]
                     ?[[param-s (станция метро?(, param-d)(искл))|param-s]]

?[[Файл:Logo train transilien.svg|15px|link=param-r/23|бсвл]]
[[Файл:Moskwa Metro Line param-1 alt.svg|15px|link=param-l1..сплиний(param-1)|бсвл]]
?[[Файл:Moskwa Metro Line param-2/34 alt.svg|15px|link=param-l2/34..сплиний(param-2/34)|бсвл]]
?[[param-l1|param-cn]]
?[[param-c (станция МЦК)|param-c]]
?[[param-m (станция монорельса)|param-m]]
?nodisambig([[param-s (станция метро?(, param-d)(искл))|param-s]])
?param-sn

]==]
return {station = station, line = line}