Перейти к содержанию

Модуль:Таблица истории

Материал из LemonCraft Wiki

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

local p = {}
local tableHead
local mode = nil
local currentVersion = nil
local currentExpVersion = nil
local currentConsoleVersions = {
	xbox360 = nil,
	xbone = nil,
	ps3 = nil,
	ps4 = nil,
	psvita = nil,
	wiiu = nil,
	switch = nil
}
local consoleRowspanIndexes
local consoleRowspans
local rowspanIndex
local rowspans
local versionLink = require( 'Модуль:Ссылка на версию' ).main

local editionAlias = {
['java pre-classic'] = "java pre-Classic",
['java classic'] = "java Classic",
['java indev'] = "java Indev",
['java infdev'] = "java Infdev",
['java alpha'] = "java Alpha", ['java edition alpha'] = "java Alpha",
['java beta'] = "java Beta", ['java edition beta'] = "java Beta",
je = "java", java = "java", ['java edition'] = "java",
['java edition upcoming'] = "java upcoming", ['java upcoming'] = "java upcoming", ['upcoming java'] = "java upcoming", ['upcoming java edition'] = "java upcoming", ['java запланированное'] = "java upcoming",
['pe alpha'] = "pocket Alpha", ['pocket alpha'] = "pocket Alpha", ['pocket edition alpha'] = "pocket Alpha",
pe = "pocket", pocket = "pocket", ['pocket edition'] = "pocket",
ce = "console", lce = "console", console = "console", ['legacy console'] = "console", ['console edition'] = "console", ['legacy console edition'] = "console",
be = "bedrock", bedrock = "bedrock", ['bedrock edition'] = "bedrock",
['be upcoming'] = "bedrock upcoming", ['bedrock upcoming'] = "bedrock upcoming", ['bedrock edition upcoming'] = "bedrock upcoming", ['upcoming bedrock'] = "bedrock upcoming", ['upcoming bedrock edition'] = "bedrock upcoming", ['bedrock запланированное'] = "bedrock upcoming",
['3ds'] = "new3ds", new3ds = "new3ds", ['new 3ds'] = "new3ds", ['new nintendo 3ds edition'] = "new3ds",
realms = "realms",
pi = "pi", ['pi edition'] = "pi", ['raspberry pi'] = "pi",
edu = "minecraftedu", minecraftedu = "minecraftedu",
education = "education", ['education edition'] = "education",
['education upcoming'] = "education upcoming", ['education edition upcoming'] = "education upcoming", ['upcoming education'] = "education upcoming", ['upcoming education edition'] = "education upcoming", ['education запланированное'] = "education upcoming",
ps = "ps",
xbox360 = "xbox360", ['xbox 360'] = "xbox360", ['xbox 360 edition'] = "xbox360",
ps4 = "ps4", playstation4 = "ps4", ['playstation 4'] = "ps4", ['playstation 4 edition'] = "ps4",
earth = "earth", ['minecraft earth'] = "earth",
dungeons = "dungeons", ['minecraft dungeons'] = "dungeons",
['dungeons arcade'] = "dungeons arcade", ['minecraft dungeons arcade'] = "dungeons arcade",
legends = "legends", ['minecraft legends'] = "legends",
china = "china", ['china edition'] = "china",
bs = "bedrock server", bds = "bedrock server", ['bedrock server'] = "bedrock server", ['bedrock dedicated server'] = "bedrock server",
['?'] = "неизвестно", ['неизвестно'] = "неизвестно"
}

local headerText = {
	['java pre-Classic']   = "[[Pre-Classic (Java Edition)|Версии pre-Classic ''Java Edition'']]",
	['java Classic']       = "[[Classic (Java Edition)|Classic-версии ''Java Edition'']]",
	['java Indev']         = "[[Indev (Java Edition)|Indev-версии ''Java Edition'']]",
	['java Infdev']        = "[[Infdev (Java Edition)|Infdev-версии ''Java Edition'']]",
	['java Alpha']         = "[[Alpha (Java Edition)|Альфа-версии ''Java Edition'']]",
	['java Beta']          = "[[Beta (Java Edition)|Бета-версии ''Java Edition'']]",
	['java']               = "''[[История версий Java Edition|Java Edition]]''",
	['java upcoming']      = "[[Запланированный контент (Java Edition)|Запланированные версии ''Java Edition'']][[Категория:Запланированное (Java Edition)]]",
	['pocket Alpha']       = "[[Alpha (Pocket Edition)#Alpha|Альфа-версии ''Pocket Edition'']]",
	['pocket']             = "''[[Pocket Edition]]''",
	['bedrock']            = "''[[История версий (Bedrock Edition)#Официальный релиз|Bedrock Edition]]''",
	['bedrock upcoming']   = "[[Запланированный контент (Bedrock Edition)|Запланированные версии ''Bedrock Edition'']][[Категория:Запланированное (Bedrock Edition)]]",
	['minecraftedu']       = "''[[MinecraftEdu#Версии|MinecraftEdu]]''",
	['education']          = "''[[История версий (Education Edition)|Minecraft Education]]''",
	['education upcoming'] = "[[Запланированный контент (Minecraft Education)|Запланированные версии ''Minecraft Education'']][[Категория:Запланированное (Minecraft Education)]]",
	['china']              = "''[[China Edition#История|China Edition]]''",
	['bedrock server']     = '[[Bedrock Dedicated Server#История|Realms Plus и Bedrock Dedicated Server]]',
	['console']            = '[[История версий (Legacy Console Edition)|Legacy Console Edition]]',
	['realms']             = '[[Realms#История|Realms]]',
	['new3ds']             = "''[[История версий (New Nintendo 3DS Edition)|New Nintendo 3DS Edition]]''",
	['pi']                 = "''[[Pi Edition#Выпуск|Pi Edition]]''",
	['xbox360']            = "''[[История версий (Legacy Console Edition)|Xbox 360 Edition]]''",
	['ps4']                = "''[[История версий (Legacy Console Edition)|PlayStation 4 Edition]]''",
	['earth']              = "''[[Earth:История версий|Minecraft Earth]]''",
	['dungeons']           = "''[[Dungeons:История версий|Minecraft Dungeons]]''",
	['dungeons arcade']    = "''[[Dungeons:Arcade|Minecraft Dungeons Arcade]]''",
	['legends']            = "''[[Legends:История версий|Minecraft Legends]]''",
	['неизвестно']         = 'Неизвестно[[Категория:Истории с неизвестными версиями]]'
}

local versionLinks = {
	['java upcoming'] = 'java',
	['bedrock upcoming'] = 'bedrock',
	['education upcoming'] = 'education',
	['bedrock server'] = 'Bedrock Dedicated Server',
	['dungeons arcade'] = 'Dungeons:' -- Это необходимо, иначе модуль «Ссылка на версию» генерирует неверную ссылку на статью об аркаде
}

local sortKeys = {
	['java 1.0.0'] = "A",
	['java 1.1'] = "B",
	['java 1.2.1'] = "C",
	['java 1.3.1'] = "D",
	['java 1.4.2'] = "E",
	['java 1.5'] = "F",
	['java 1.6.1'] = "G",
	['java 1.7.2'] = "F",
	['java 1.8'] = "G",
	['java 1.9'] = "H",
	['java 1.10'] = "I",
	['java 1.11'] = "J",
	['java 1.12'] = "K",
	['java 1.13'] = "L",
	['java 1.14'] = "M",
	['java 1.15'] = "N",
	['java 1.16'] = "O",
	['java texture update'] = "_",
	['java indev 0.31'] = "0",
	['java alpha v1.2.0'] = "2",
	['java beta 1.6'] = "6",
	['java beta 1.8'] = "8",
	['pocket alpha v0.8.0'] = "A",
	['pocket alpha 0.8.0'] = "A",
	['pocket alpha v0.9.0'] = "B",
	['pocket alpha 0.9.0'] = "B",
	['pocket alpha v0.10.0'] = "C",
	['pocket alpha 0.10.0'] = "C",
	['pocket alpha v0.11.0'] = "D",
	['pocket alpha 0.11.0'] = "D",
	['pocket alpha v0.12.1'] = "E",
	['pocket alpha 0.12.1'] = "E",
	['pocket alpha v0.13.0'] = "F",
	['pocket alpha 0.13.0'] = "F",
	['pocket alpha v0.14.0'] = "G",
	['pocket alpha 0.14.0'] = "G",
	['pocket alpha v0.15.0'] = "H",
	['pocket alpha 0.15.0'] = "H",
	['pocket alpha v0.16.0'] = "I",
	['pocket alpha 0.16.0'] = "I",
	['pocket 1.0.0'] = "X",
	['pocket 1.1.0'] = "Y",
	['pocket 1.1.3'] = "Z",
	['bedrock 1.2.0'] = "A",
	['bedrock 1.2.13'] = "B",
	['bedrock 1.4.0'] = "C",
	['bedrock 1.5.0'] = "D",
	['bedrock 1.6.0'] = "E",
	['bedrock 1.7.0'] = "F",
	['bedrock 1.8.0'] = "G",
	['bedrock 1.9.0'] = "H",
	['bedrock 1.10.0'] = "I",
	['bedrock 1.11.0'] = "J",
	['bedrock 1.12.0'] = "K",
	['bedrock 1.13.0'] = "L",
	['bedrock 1.14.0'] = "M",
	['bedrock 1.14.60'] = "M",
	['bedrock 1.16.0'] = "N",
	['bedrock 1.16.100'] = "N"
}

local function getUnknownCate()
	if(mode==nil or mode=='неизвестно') then return '' end
	local sortKey = sortKeys[mode..(currentVersion or '')] or "*"
	return table.concat{"[[Категория:Истории с неизвестными версиями/", mode, "|", sortKey, "]]"}
end

local function resetConsole()
	currentConsoleVersions.xbox360 = nil
	currentConsoleVersions.xbone = nil
	currentConsoleVersions.ps3 = nil
	currentConsoleVersions.ps4 = nil
	currentConsoleVersions.psvita = nil
	currentConsoleVersions.wiiu = nil
	currentConsoleVersions.switch = nil
end

local function reset()
	currentVersion = nil
	currentExpVersion = nil
	resetConsole()
end

local function footReset()
	mode = nil
	reset()
end

local function getVersionLink(link,text,isDev)
	if(link=='нет') then
		if(text=='неизвестно' or text=='?') then return '?'..getUnknownCate() end
		if(isDev and text=='java') then return '' end
		return text
	end
	if(link=='вер') then
		if(text=='неизвестно' or text=='?') then return '[[:Категория:Истории с неизвестными версиями|?]]'..getUnknownCate() end
		if(isDev and text=='java') then return '' end
		if((not isDev) and (mode=='realms')) then return text end
		local c
			if(not isDev) then
				if(mw.text.trim(text)=='Pre-release' and mode == 'pocket Alpha') then c = 'pocket Pre-release'
				else c = (versionLinks[mode] or mode)..' '..text
				end
			else
				c = text:lower()
				if(c:match('^test build') or c:match('^pre%-release') or c:match('^build') or c:match('^20[01]') or c:match('^release candidate') or c:match('^experimental snapshot')) then c = currentVersion..' '..text
				elseif(c:match('^preview [0-9]')) then c = text -- Preview-версии Bedrock Edition
				elseif(c:match('^pre')) then c = currentVersion..'-'..text
				elseif(c:match('^release')) then c = currentVersion
				else c = text
				end
				c = (versionLinks[mode] or mode)..' '..c
			end
		return versionLink({c,text:gsub( '^%((.*)%)$', '%1' )})
	end
	local cat = ''
	if(text=='неизвестно' or text=='?') then cat = getUnknownCate() end
	if(link:find('//',1,true)) then return '['..link..' '..text..']'..cat else return '[['..link..'|'..text..']]'..cat end
end


local function consoleVersionLink(platform,version,link)
	if(version=='нет') then return '' end
	if(version=='неизвестно' or version=='?') then return '?'..getUnknownCate() end
	if(link) then
		if(link=='нет') then return version end
		if(link:find('//',1,true)) then return '['..link..' '..version..']' else return '[['..link..'|'..version..']]' end
	end
	local r = platform..' '..version
	return versionLink({r,version})
end

local oldPsVersionFormat = false;
local function addConsoleVersions(platform,version,link,prnt)
    if(((version~=nil and version~='') and version == currentConsoleVersions[platform]) or ((version==nil or version=='') and currentConsoleVersions[platform]~=nil))
    then
        return
    end
    prnt('<th class="nowrap" rowspan="')
    currentConsoleVersions[platform] = version or "нет"
    consoleRowspanIndexes[platform] = consoleRowspanIndexes[platform] + 1
    prnt(consoleRowspans[platform][consoleRowspanIndexes[platform]]..'">')
    prnt(consoleVersionLink(platform,version or 'нет',link))
    prnt('</th>')
end

local function consoleSubHeader(content, prnt)
	prnt("<th style=\"border-style: none dashed\">" .. content .. "</th>")
end

local function processLine(args, prnt)
	local snapRows = 1
	for i,_ in ipairs(args) do if(i>3) then snapRows = snapRows+1 end end
	
	-- Глава или подвал
	if(args[1] ~= nil and args[1] ~= '') then
		local temp = (args[1]):lower()
		if (temp == 'подвал') then
			prnt('</table>')
			footReset()
			tableHead = 0
			return
		end
		mode = editionAlias[temp] or args[1]
		reset()
		prnt('<tr class="collapsible collapsible-rows"><th colspan="8" style="border-bottom: none">')
		prnt(headerText[mode] or ('[['.. mode ..']]'))
		prnt('</th></tr>')
		if mode == 'console' then
			prnt('<tr style="font-size: smaller">')
			consoleSubHeader("[[Xbox 360 Edition|Xbox&nbsp;360]]", prnt)
			consoleSubHeader("[[Xbox One Edition|Xbox&nbsp;One]]", prnt)
			consoleSubHeader("[[PlayStation 3 Edition|PS3]]", prnt)
			consoleSubHeader("[[PlayStation 4 Edition|PS4]]", prnt)
			consoleSubHeader("[[PlayStation Vita Edition|PS&nbsp;Vita]]", prnt)
			consoleSubHeader("[[Wii U Edition|Wii U]]", prnt)
			consoleSubHeader("[[Nintendo Switch Edition|Switch]]", prnt)
			consoleSubHeader("", prnt)
			prnt("</tr>")
		end
		return
	end
	
	-- Строки
	
	prnt('<tr>')
	
	if((mode == 'console') and (args['xbox'] or args['xbone'] or args['ps3'] or args['ps4'] or args['psvita'] or args['wiiu'] or args['switch'] )) then
		currentVersion = nil
		
		if(args[3] ~= nil and args[3] ~= '') then
			snapRows = snapRows+1
		end
		
		addConsoleVersions("xbox360",args['xbox'],args['xboxссылка'],prnt)
		addConsoleVersions("xbone",args['xbone'],args['xboneссылка'],prnt)
		addConsoleVersions("ps3",args['ps3'],args['ps3ссылка'],prnt)
		addConsoleVersions("ps4",args['ps4'],args['ps4ссылка'],prnt)
		addConsoleVersions("psvita",args['psvita'],args['psvitaссылка'],prnt)
		addConsoleVersions("wiiu",args['wiiu'],args['wiiuссылка'],prnt)
		addConsoleVersions("switch",args['switch'],args['switchссылка'],prnt)
		
		prnt('<td>'..args[2]..'</td></tr>')
		
		for k,v in ipairs(args) do if(k>2) then prnt('<tr><td>'..v..'</td></tr>') end end
		
		return
	end
	
	-- Другие версии:
	
	resetConsole()
	if((args['сборка'] == nil) or (args[2] and args[2]~='') or (args['эксп'] and args['эксп']~='' and args['эксп'] ~= currentExpVersion)) then
		currentVersion = nil
		currentExpVersion = nil
		prnt('<th ')
		if( not (args['ссылка'] or args[2]:find('(',1,true))) then prnt('class="nowrap"') end
		prnt(' rowspan="')
		if( args['эксп'] ~= nil) then
			currentExpVersion = args['эксп']
		end
		if( args['сборка'] ~= nil) then
			currentVersion = args[2]
			rowspanIndex = rowspanIndex + 1
			prnt(rowspans[rowspanIndex]..'" colspan="3">')
		else
			prnt(snapRows .. '" colspan="7">')
		end
		prnt(getVersionLink(args['ссылка'] or 'вер', args[2],false))
		if (args['эксп'] ~= nil or args['эксперимент'] ~= nil) then
			prnt("<div class=\"historytable-experiment\"><div>Эксперимент</div></div><span>"..(args['эксп'] or args['эксперимент']).."</span>")
		end
		prnt('</th>')
	end
	
	if(args['сборка'] ~= nil) then
		prnt('<th colspan="4" rowspan="' .. snapRows ..'">')
		prnt(getVersionLink(args['предссылка'] or 'вер', args['сборка'],true))
		prnt('</th>')
	end
	
	if args[3] then
		prnt('<td>'..args[3]..'</td></tr>')
	end
	for k,v in ipairs(args) do if(k>3) then prnt('<tr><td>'..v..'</td></tr>') end end
	
	return
end

-- Следующая функция помещает все аргументы в строку JSON
function p.printArgs(frame)
	return mw.text.jsonEncode(frame:getParent().args)
end

-- Отмена сериализации для разбора синтаксиса
function deserialize(args)
	local e
	local out = {}
	for k, v in pairs(args) do
		e, out[k] = pcall( mw.text.jsonDecode, v )
		if not e then
			local errorCat = ''
			local errorMsg = mw.message.new( 'scribunto-common-error-category' )
			if not errorMsg:isDisabled() then
				errorCat = '[[Категория:'..errorMsg:plain()..']]'
			end
			out[k] = { '', 'неизвестно', v..' <strong class="error">Ошибка Lua: '..out[k]..errorCat..' Ввод:'.. v ..'</strong>' }
		end
	end
	return out
end

local function countConsoleRowspans(platform,version,snapRows)
	if(((version~=nil and version~='') and version == currentConsoleVersions[platform]) or ((version==nil or version=='') and currentConsoleVersions[platform]~=nil))
	then
		consoleRowspans[platform][consoleRowspanIndexes[platform]] = consoleRowspans[platform][consoleRowspanIndexes[platform]] + snapRows
		return
	end
	currentConsoleVersions[platform] = version or "нет"
	consoleRowspanIndexes[platform] = consoleRowspanIndexes[platform] + 1
	consoleRowspans[platform][consoleRowspanIndexes[platform]] = (consoleRowspans[platform][consoleRowspanIndexes[platform]] or 0) + snapRows
end


local function countRowspan(args)
	local snapRows = 1
	for i,_ in ipairs(args) do if(i>3) then snapRows = snapRows+1 end end
	
	-- Глава или подвал
	if(args[1] ~= nil and args[1] ~= '') then
		local temp = (args[1]):lower()
		if (temp == 'подвал') then
			footReset()
			return
		end
		mode = editionAlias[temp] or args[1]
		reset()
		return
	end
	
	-- Строки
	
	if((mode == 'console') and (args['xbox'] or args['xbone'] or args['ps3'] or args['ps4'] or args['psvita'] or args['wiiu'] or args['switch'] )) then
		currentVersion = nil
		
		if(args[3] ~= nil and args[3] ~= '') then
			snapRows = snapRows+1
		end
		
		countConsoleRowspans("xbox360",args['xbox'],snapRows)
		countConsoleRowspans("xbone",args['xbone'],snapRows)
		countConsoleRowspans("ps3",args['ps3'],snapRows)
		countConsoleRowspans("ps4",args['ps4'],snapRows)
		countConsoleRowspans("psvita",args['psvita'],snapRows)
		countConsoleRowspans("wiiu",args['wiiu'],snapRows)
		countConsoleRowspans("switch",args['switch'],snapRows)
		
		return
	end
	
	-- Другие версии
	
	resetConsole()
	if((args['сборка'] == nil) or (args[2] and args[2]~='') or (args['эксп'] and args['эксп']~='' and args['эксп'] ~= currentExpVersion)) then
		currentVersion = nil
		currentExpVersion = nil
		if(args['сборка'] ~= nil) then
			currentVersion = args[2]
			rowspanIndex = rowspanIndex + 1
		end
	end
	
	if(args['сборка'] ~= nil) then
		rowspans[rowspanIndex] = (rowspans[rowspanIndex] or 0) + snapRows
	end
	return
end

local function initRowspans()
	rowspans = {}
	consoleRowspans = {
		xbox360 = {},
		xbone = {},
		ps3 = {},
		ps4 = {},
		psvita = {},
		wiiu = {},
		switch = {}
	}
end

local function resetRowspanIndexes()
	rowspanIndex = 0
	consoleRowspanIndexes = {
		xbox360 = 0,
		xbone = 0,
		ps3 = 0,
		ps4 = 0,
		psvita = 0,
		wiiu = 0,
		switch = 0
	}
end

function p.main(frame)
	return p._main(frame:getParent().args)
end

function p._main(args)
	local lines = deserialize(args)
	
	initRowspans()
	resetRowspanIndexes()
	for _,v in ipairs(lines) do
		countRowspan(v)
	end
	
	resetRowspanIndexes()
	tableHead=0
	local result = {}
	for _,v in ipairs(lines) do
		if(tableHead~=1) then
			table.insert(result, '<table class="wikitable pixel-image" data-description="История">')
			tableHead = 1
		end
		processLine(v,function(a) table.insert(result, a) end)
	end
	if tableHead~=0 then
		table.insert(result, '</table>')
		footReset()
		tableHead = 0
	end
	return table.concat(result)
end

return p