Module:沙盒/盐棋/Sandbox:修订间差异

来自Arcaea中文维基
(调整)
(songtable)
第1行: 第1行:
local getArgs = require 'Module:Arguments'.getArgs
-- local link = require 'Module:Link'._link
local mad = require 'Module:AnotherData'
local mad = require 'Module:AnotherData'
local lang = mw.language.getContentLanguage()
local p = {}
local p = {}


local linkPool = {}
local bgLinkF = '[[:分类:采用%s背景的曲目|%s]]'
local mLink = {}
local bgCatF = '采用%s背景的曲目'
local mSong = {}
local function array(...) return setmetatable({...}, {__index = table}) end
for _, song in ipairs(mad.listOf 'songs') do
local function onlySupScript(s) return mw.getCurrentFrame().expandTemplate {title = '仅', args = {s, '', '图片角标'}} end
local query = mad.songQueryWrap(song)
local function vdValidation(v, d) return v and d and {v, d} end
local link = query.linkTitle
local function labelText(text) return mw.html.create 'span':addClass 'bg-c':wikitext(text) end
linkPool[link] = true
local function dateCov(dateBox, data, plat)
mSong[song.id] = song
local version, date = unpack(data or {})
mLink[song.id] = link
dateBox:tag 'div':node(labelText(plat)):done()
:tag 'div':wikitext(version):newline():wikitext('(', date, ')'):done()
end
end
local function span(len) if len > 1 then return 'span-' .. len end end


function p.world(frame)
-- .container
local world = mw.title.new('世界模式地图详表 (移动版' .. frame.args[1] .. ')'):getContent()
-- .img-tab#tab-a
local res = {}
-- .img-tab-part.{cls} * n
for name, wtb in world:gmatch '== *([^B].-) *==[^={]+(%b{})' do
-- {text}
local tot
-- .tab-text-a.active? * n
for stair, reward in wtb:gmatch '| *(%d+)[0-9()%-| ]+(%b[])' do
-- {file}[ 画师]{jacket}
if linkPool[reward:sub(3, -3)] then
---@param view table<integer,table<integer,string>>
tot = tot or tonumber(wtb:match '| *(%d+)[^\n]+\n|%-\n| *总计') - 1
---@param activeIdx integer?
table.insert(res, ('|-\n|%s||%s||%d/%d'):format(reward, name, tonumber(stair) - 1, tot))
---@return table
end
local function createContainer(view, activeIdx)
end
activeIdx = activeIdx or 1
local container = mw.html.create 'div':addClass 'container'
local tab = container:tag 'div':addClass 'img-tab':attr('id', 'tab-a')
for _, v in ipairs(view) do
local text, cls = v[1], v[2] or 'normal'
tab:tag 'div':wikitext(text):addClass 'img-tab-part':addClass(cls):done()
end
for idx, v in ipairs(view) do
local file, jacket = v[3], v[4]
container
:tag 'div':addClass 'tab-text-a':addClass(idx == activeIdx and 'active' or nil)
:wikitext('[[文件:', file, '|', 256, 'px|none]]')
:node(labelText ' 画师')
:wikitext(jacket)
:done()
end
end
return table.concat(res, '\n')
return container
end
end
 
local function getImage(args, song)
local templates = {
local id = song or song.id
[0] = '$credit 残 片',
local argPic = args[' 片'] or args[' 曲绘']
'$grade通关 $song_id $song_difficulty',
local argArtist = args[' 图片'] or args[' 曲绘']
' 游玩 $song_id $song_difficulty',
if args['Beyond画师'] then
'$grade通关 $song_id $song_difficulty$times回',
return createContainer {
"$1 <br>''' ''' $2",
{'Normal', nil, argPic, argArtist},
' 个人游玩潜力值 $rating 或以上',
{'Beyond', 'byd', args['Beyond曲绘'], args['Beyond画师']},
' 通关$count首$rating$ratingPlus难度曲目',
}
}
end
local handlers = {}
return mw.html.create 'div'
local linkize = '[[%s]]'
:wikitext('[[文件:', id and 'Songs ' .. id .. '.jpg' or (argPic), '|', 256, 'px|none]]')
function handlers.song_id(v) return linkize:format(mLink[v]) end
:node(labelText ' 画师')
function handlers.song_difficulty(v) return ({[0] = '[PST]', '[PRS]', '[FTR]', '[BYD]'})[v] end
:wikitext(argArtist)
function handlers.grade(v) return v == 0 and '' or (' 以 「%s」 或以上成绩'):format(({'C', 'B', 'A', 'AA', 'EX'})[v]) end
function handlers.rating(v) return v > 13 and ('%.2f'):format(v / 100) or v end
function handlers.ratingPlus(v) return v and '+' or '' end
local function stringify(cond)
local res = templates[cond.type]:gsub('%$([a-zA-Z12_]+)', function(k)
local nk = tonumber(k)
if nk then return stringify(cond.conditions[nk]) end
if handlers[k] then return handlers[k](cond[k]) end
return cond[k]
end)
return res
end
end
 
local function tabCustom(args)
local names = {'frag', 'prev', 'ptt'}
local i = 1
local function judgeCond(type)
local res = array()
if type == 0 then
while args['tab' .. i] do
return 'frag'
res:insert {mw.ustring.match(args['tab' .. i], '([^/]*)/([^/]*)/([^/]*)/(.*)')}
elseif type == 5 then
i = i + 1
return 'ptt'
elseif type <= 100 and type ~= 5 then
return 'prev'
end
end
return res, args['默认图片序号']
end
end
local function createRow()
local function merge(charts, field)
local res = {}
local res = array()
for _, k in ipairs(names) do res[k] = 0 end
local cur, len = charts[1][field], 1
for _, c in ipairs(charts) do
local e = c[field]
if e == cur then
len = len + 1
else
res:insert {cur, len}
cur = e
len = 1
end
end
res:insert {cur, len}
return res
return res
end
end
local function judgeRow(row)
local function getSet(sm, sns)
local res = {'ulk'}
--% 要求名字相同
for _, k in ipairs(names) do if row[k] > 0 then table.insert(res, k) end end
local qm, qns = mad.packQueryWrap(sm and sm.set, 'mobile'), mad.packQueryWrap(sns and sns.set, 'ns')
return ('class="%s"'):format(table.concat(res, ' '))
local namem, namens = qm.section ~= 'unknown' and qm.name or nil, qns.section ~= 'unknown' and qns.name or nil
local name = namem or namens
if not name then return nil end
local res = {name}
if namens and namens ~= name then table.insert(res, namens .. onlySupScript 'NS版') end
if #res > 1 then res[1] = res[1] .. onlySupScript '移动版' end
return table.concat(res, '<br>')
end
end
-- TODO:displaytitle lowercase
local function getById(list, id)
for _, k in ipairs(list) do if k.id == id then return k end end
end
local function getByTitle(list, title)
for _, k in ipairs(list) do if k.title_localized.en == title then return k end end
end
local function auto(args)
local category = {}
local function addCategory(item)
table.insert(category, '[[分类:' .. item .. ']]')
end
local notice = {}
--% "曲名"必存在,"id"必非空串
local songKey, getDatum = args['id'], getById
if not songKey then songKey, getDatum = mw.text.decode(args['曲名']), getByTitle end
local lm, lns
if args['愚人节'] then
lm, lns = mad.listOfReserve(), array()
elseif songKey == 'Last' then
lm, lns = mad.listOfReserve(), mad.listOfReserve()
else
lm, lns = mad.listOf('songs', 'mobile'), mad.listOf('songs', 'ns')
end
local sm, sns = getDatum(lm, songKey), getDatum(lns, songKey)
--% 可能平台不一致
local set = args['曲包'] or getSet(sm, sns)
local platCode = (sm and 1 or 0) + (sns and 2 or 0)
local song = sm or sns
if not (sns and sns ~= song) then sns = {difficulties = array()} end
if not song then
notice.data = true
song = mad.listOfReserve()[1]
song.title_localized.en = songKey
end
local box = mw.html.create 'div':addClass 'infotable'
local header = box:tag 'div':addClass 'header bg-c':wikitext(song.title_localized.en)
if song.title_localized.ja then header:newline():node 'span':attr {lang = 'ja'}:wikitext(song.title_localized.ja) end
if song.title_localized['zh-Hans'] then header:newline():wikitext(song.title_localized['zh-Hans']) end
box:tag 'div':addClass 'figure':node(args['tab1'] and createContainer(tabCustom(args)) or getImage(args, song))
--% :create''
local main = box:tag 'div':addClass 'main'
addCategory(({'移动版曲目', 'NS版曲目', '双平台曲目'})[platCode])
local sideCode = (tonumber(args['侧']) or song.side) + 1
box:addClass(({'light', 'conflict', 'colorless'})[sideCode])
addCategory(({'光芒侧曲目', '纷争侧曲目', '消色侧曲目'})[sideCode])
local colTags = array()
for idx, diff in ipairs(song.difficulties) do
colTags[idx] = diff['@tag'] or ({[0] = 'Past', 'Present', 'Future', 'Beyond', 'Eternal'})[diff.ratingClass]
end


function p.main()
local artist = args['编曲'] or args['曲师'] or song.artist
local view = {}
if not set then notice.pack = true end
for _, chartUlk in ipairs(mad.listOf 'unlocks') do
-- addCategory %set曲包曲目
local id, rc = chartUlk.songId, chartUlk.ratingClass + 1
local duration = args['时长']
for _, cond in ipairs(chartUlk.conditions) do
if not duration then notice.duration = true end
local className = judgeCond(cond.type)
local bpm = args['BPM'] or song.bpm
if className then
main:tag 'div':addClass 'gc-1 bg-c':wikitext '曲目信息'
local row = view[id]
for _, v in ipairs {{'曲师', artist}, {'曲包', set}, {'时长', duration}, {'BPM', bpm},} do
if not row then
local tag, data = unpack(v)
row = createRow()
main:tag 'div':addClass 'bg-c':wikitext(tag):done()
view[id] = row
:tag 'div':addClass 'gc-2':wikitext(data)
end
end
row[className] = row[className] + 1
 
local cell = row[rc]
local bg = args['背景'] or song.bg
if not cell then
if bg then addCategory(bgCatF:format(bg)) end
cell = {}
local vd = vdValidation(args['更新版本'], args['更新时间'])
row[rc] = cell
if not vd then notice.vd = true end
end
local vdNS
table.insert(cell, tostring(mw.html.create 'span':addClass 'ulk':addClass(className):wikitext(stringify(cond))))
if sns.id then
vdNS = vdValidation(args['更新版本NS'], args['更新时间NS'])
if not vdNS then notice.vd = true end
end
 
local charts = array()
--% 假定ns难度序列是主难度序列的前缀
for idx, tag in ipairs(colTags) do
local chart = {}
charts:insert(chart)
local diff = song.difficulties[idx]
 
local class = ({[0] = 'PST', 'PRS', 'FTR', 'BYD', 'ETR'})[diff.ratingClass]
chart.display = ('<span class="text-%s">[%s]</span>'):format(lang:lc(class), tag)
addCategory(class .. chart.rating .. '级曲目')
local function chartBasic(df, vd, s)
chart['rating' .. s] = args[tag .. '等级' .. s] or (df.rating .. (df.ratingPlus and '+' or ''))
chart['note' .. s] = args[tag .. 'Note' .. s]
chart['vdOverride' .. s] = vdValidation(args[tag .. '更新版本' .. s], args[tag .. '更新时间' .. s])
if df.date and not chart['vdOverride' .. s] then notice.vd = true end
chart['vdOverride' .. s] = chart['vdOverride' .. s] or vd
end
 
chartBasic(diff, vd, '')
if not chart.note then notice.note = true end
 
chart.designer = args[tag .. 'Note编写'] or args['note编写'] or diff.chartDesigner
chart.bgOverride = args[tag .. ' 背景'] or diff.bg
if chart.bgOverride then addCategory(bgCatF:format(chart.bgOverride)) end
chart.bgOverride = chart.bgOverride or bg
if diff.title_localized then header:newline():wikitext(diff.title_localized.en, ' ', chart.display) end
local diffNS = sns.difficulties[idx]
if diffNS then
-- 仅移动版
chartBasic(diffNS, vdNS, 'NS')
if diffNS.has_controller_alt_chart then
notice.alt = true
if not chart.noteNS then notice.note = true end
end
end
end
end
end
end
 
main:tag 'div':addClass 'gc-1 bg-c':wikitext '谱面信息'
local texts = {}
main:tag 'div':addClass 'bg-c':wikitext '难度'
local rowFormat = '|-%s\n|[[%s]]' .. ('||%s'):rep(3)
for _, c in ipairs(charts) do
local sectionCode = {unknown = 0, single = 1, free = 2, mainstory = 3, sidestory = 4, collab = 5}
main:tag 'div':wikitext(c.display)
for id, row in pairs(view) do
end
local song = mSong[id]
main:tag 'div':addClass 'bg-c':wikitext '等级'
local packItem = mad.packQueryWrap(song.set, 'mobile')
for _, c in ipairs(charts) do
local rowText = {}
main:tag 'div':wikitext(c.rating)
for i = 1, 3 do
end
local cell = row[i]
main:tag 'div':addClass 'bg-c':wikitext 'note数量'
if not cell or #cell == 0 then
for _, c in ipairs(charts) do
rowText[i] = ' '
main:tag 'div':wikitext(c.note)
else
end
rowText[i] = table.concat(cell, '<br>')
main:tag 'div':addClass 'bg-c':wikitext '谱面设计'
end
for _, tp in ipairs(merge(charts, 'designer')) do
local data, len = unpack(tp)
main:tag 'div':addClass(span(len)):wikitext(data)
end
if platCode == 3 then
main:tag 'div':addClass 'bg-c':wikitext ' 等级NS'
for _, c in ipairs(charts) do
main:tag 'div':wikitext(c.ratingNS)
end
end
if notice.alt then
addCategory '多模式谱面有差异的曲目'
main:tag 'div':addClass 'bg-c':wikitext 'note数量<br>(Joy-Con)'
for _, c in ipairs(charts) do
main:tag 'div':wikitext(c.noteNS)
end
end
local className = judgeRow(row)
if id == 'lasteternity' then className = 'class="ulk"' end
table.insert(texts, {
data = rowFormat:format(className, mLink[id], unpack(rowText)),
pack = packItem['name'],
sort = {sectionCode[packItem['section']], packItem['numero'], song.date},
})
end
end
main:tag 'div':addClass 'bg-c':wikitext '背景'
for _, tp in ipairs(merge(charts, 'bgOverride')) do
local data, len = unpack(tp)
main:tag 'div':addClass(span(len)):wikitext(data and bgLinkF:format(data))
end


table.sort(texts, function(a, b)
main:tag 'div':addClass 'bg-c':css(platCode == 3 and {gridRow = 'span 2'} or {}):wikitext '更新时间'
a, b = a.sort, b.sort
for _, tp in ipairs(merge(charts, 'vdOverride')) do
for i = 1, 3 do
local data, len = unpack(tp)
local d = a[i] - b[i]
dateCov(main:tag 'div':addClass(span(len)), data, '移动版')
if d ~= 0 then return d < 0 end
end
if platCode == 3 then
for _, tp in ipairs(merge(charts, 'vdOverrideNS')) do
local data, len = unpack(tp)
dateCov(main:tag 'div':addClass(span(len)), data, 'NS版')
end
end
return false
end
end)


local hybrid = {}
local noticeText = ''
local pack
for _, v in ipairs {
for _, value in ipairs(texts) do
{'data', '在Songlist中无法检查到此曲目。请尝试更新[[模板:Songlist]],检查页面名或填写正确的<code>曲名</code>参数。'},
if pack ~= value.pack then
{'duration', '此模板缺少<code>时长</code>参数,此参数无法自动读取。'},
pack = value.pack
{'pack', '未更新Packlist。曲目信息模板无法进行曲包分类。'},
table.insert(hybrid, '|-\n| colspan="4" |' .. pack)
{'vd', '此模板的更新版本是未完整状态。请添加<code>更新版本</code>与<code>更新时间</code>参数。'},
end
{'note', '此模板缺少某种<code>Note</code>参数,此参数无法自动读取。'},
table.insert(hybrid, value.data)
} do
local msg, text = unpack(v)
if notice[msg] then noticeText = noticeText .. text end
end
if noticeText ~= '' then
noticeText = mw.getCurrentFrame():expandTemplate {title = 'Collapse', args = {['标题'] = '曲目信息模板提示信息', ['状态'] = '折叠',
['标题文字方向'] = 'center', ['标题颜色'] = '#dddddd',
['内容颜色'] = '#eeeeee', ['内容样式'] = 'width:800px',
['style'] = 'display:table;width:200px', ['class'] = 'nomobile',
['内容'] = noticeText}}
category:add '缺少参数的曲目信息模板'
end
end
return tostring(box) .. notice .. (args['nocat'] and '' or table.concat(category))
end


return table.concat(hybrid, '\n')
function p.main(frame)
local args = getArgs(frame)
return auto(args)
end
end


return p
return p

2024年3月12日 (二) 22:40的版本

可在Module:沙盒/盐棋/Sandbox/doc创建此模块的帮助文档

local getArgs = require 'Module:Arguments'.getArgs
-- local link = require 'Module:Link'._link
local mad = require 'Module:AnotherData'
local lang = mw.language.getContentLanguage()
local p = {}

local bgLinkF = '[[:分类:采用%s背景的曲目|%s]]'
local bgCatF = '采用%s背景的曲目'
local function array(...) return setmetatable({...}, {__index = table}) end
local function onlySupScript(s) return mw.getCurrentFrame().expandTemplate {title = '仅', args = {s, '', '图片角标'}} end
local function vdValidation(v, d) return v and d and {v, d} end
local function labelText(text) return mw.html.create 'span':addClass 'bg-c':wikitext(text) end
local function dateCov(dateBox, data, plat)
	local version, date = unpack(data or {})
	dateBox:tag 'div':node(labelText(plat)):done()
		:tag 'div':wikitext(version):newline():wikitext('(', date, ')'):done()
end
local function span(len) if len > 1 then return 'span-' .. len end end

--	.container
--		.img-tab#tab-a
--			.img-tab-part.{cls} * n
--				{text}
--		.tab-text-a.active? * n
--			{file}[画师]{jacket}
---@param view table<integer,table<integer,string>>
---@param activeIdx integer?
---@return table
local function createContainer(view, activeIdx)
	activeIdx = activeIdx or 1
	local container = mw.html.create 'div':addClass 'container'
	local tab = container:tag 'div':addClass 'img-tab':attr('id', 'tab-a')
	for _, v in ipairs(view) do
		local text, cls = v[1], v[2] or 'normal'
		tab:tag 'div':wikitext(text):addClass 'img-tab-part':addClass(cls):done()
	end
	for idx, v in ipairs(view) do
		local file, jacket = v[3], v[4]
		container
			:tag 'div':addClass 'tab-text-a':addClass(idx == activeIdx and 'active' or nil)
			:wikitext('[[文件:', file, '|', 256, 'px|none]]')
			:node(labelText '画师')
			:wikitext(jacket)
			:done()
	end
	return container
end
local function getImage(args, song)
	local id = song or song.id
	local argPic = args['图片'] or args['曲绘']
	local argArtist = args['图片'] or args['曲绘']
	if args['Beyond画师'] then
		return createContainer {
			{'Normal', nil, argPic, argArtist},
			{'Beyond', 'byd', args['Beyond曲绘'], args['Beyond画师']},
		}
	end
	return mw.html.create 'div'
		:wikitext('[[文件:', id and 'Songs ' .. id .. '.jpg' or (argPic), '|', 256, 'px|none]]')
		:node(labelText '画师')
		:wikitext(argArtist)
end
local function tabCustom(args)
	local i = 1
	local res = array()
	while args['tab' .. i] do
		res:insert {mw.ustring.match(args['tab' .. i], '([^/]*)/([^/]*)/([^/]*)/(.*)')}
		i = i + 1
	end
	return res, args['默认图片序号']
end
local function merge(charts, field)
	local res = array()
	local cur, len = charts[1][field], 1
	for _, c in ipairs(charts) do
		local e = c[field]
		if e == cur then
			len = len + 1
		else
			res:insert {cur, len}
			cur = e
			len = 1
		end
	end
	res:insert {cur, len}
	return res
end
local function getSet(sm, sns)
	--% 要求名字相同
	local qm, qns = mad.packQueryWrap(sm and sm.set, 'mobile'), mad.packQueryWrap(sns and sns.set, 'ns')
	local namem, namens = qm.section ~= 'unknown' and qm.name or nil, qns.section ~= 'unknown' and qns.name or nil
	local name = namem or namens
	if not name then return nil end
	local res = {name}
	if namens and namens ~= name then table.insert(res, namens .. onlySupScript 'NS版') end
	if #res > 1 then res[1] = res[1] .. onlySupScript '移动版' end
	return table.concat(res, '<br>')
end
-- TODO:displaytitle lowercase
local function getById(list, id)
	for _, k in ipairs(list) do if k.id == id then return k end end
end
local function getByTitle(list, title)
	for _, k in ipairs(list) do if k.title_localized.en == title then return k end end
end
local function auto(args)
	local category = {}
	local function addCategory(item)
		table.insert(category, '[[分类:' .. item .. ']]')
	end
	local notice = {}

	--% "曲名"必存在,"id"必非空串
	local songKey, getDatum = args['id'], getById
	if not songKey then songKey, getDatum = mw.text.decode(args['曲名']), getByTitle end
	local lm, lns
	if args['愚人节'] then
		lm, lns = mad.listOfReserve(), array()
	elseif songKey == 'Last' then
		lm, lns = mad.listOfReserve(), mad.listOfReserve()
	else
		lm, lns = mad.listOf('songs', 'mobile'), mad.listOf('songs', 'ns')
	end
	local sm, sns = getDatum(lm, songKey), getDatum(lns, songKey)
	--% 可能平台不一致
	local set = args['曲包'] or getSet(sm, sns)
	local platCode = (sm and 1 or 0) + (sns and 2 or 0)
	local song = sm or sns
	if not (sns and sns ~= song) then sns = {difficulties = array()} end
	if not song then
		notice.data = true
		song = mad.listOfReserve()[1]
		song.title_localized.en = songKey
	end

	local box = mw.html.create 'div':addClass 'infotable'
	local header = box:tag 'div':addClass 'header bg-c':wikitext(song.title_localized.en)
	if song.title_localized.ja then header:newline():node 'span':attr {lang = 'ja'}:wikitext(song.title_localized.ja) end
	if song.title_localized['zh-Hans'] then header:newline():wikitext(song.title_localized['zh-Hans']) end
	box:tag 'div':addClass 'figure':node(args['tab1'] and createContainer(tabCustom(args)) or getImage(args, song))
	--% :create''
	local main = box:tag 'div':addClass 'main'

	addCategory(({'移动版曲目', 'NS版曲目', '双平台曲目'})[platCode])
	local sideCode = (tonumber(args['侧']) or song.side) + 1
	box:addClass(({'light', 'conflict', 'colorless'})[sideCode])
	addCategory(({'光芒侧曲目', '纷争侧曲目', '消色侧曲目'})[sideCode])
	local colTags = array()
	for idx, diff in ipairs(song.difficulties) do
		colTags[idx] = diff['@tag'] or ({[0] = 'Past', 'Present', 'Future', 'Beyond', 'Eternal'})[diff.ratingClass]
	end

	local artist = args['编曲'] or args['曲师'] or song.artist
	if not set then notice.pack = true end
	-- addCategory %set曲包曲目
	local duration = args['时长']
	if not duration then notice.duration = true end
	local bpm = args['BPM'] or song.bpm
	main:tag 'div':addClass 'gc-1 bg-c':wikitext '曲目信息'
	for _, v in ipairs {{'曲师', artist}, {'曲包', set}, {'时长', duration}, {'BPM', bpm},} do
		local tag, data = unpack(v)
		main:tag 'div':addClass 'bg-c':wikitext(tag):done()
			:tag 'div':addClass 'gc-2':wikitext(data)
	end

	local bg = args['背景'] or song.bg
	if bg then addCategory(bgCatF:format(bg)) end
	local vd = vdValidation(args['更新版本'], args['更新时间'])
	if not vd then notice.vd = true end
	local vdNS
	if sns.id then
		vdNS = vdValidation(args['更新版本NS'], args['更新时间NS'])
		if not vdNS then notice.vd = true end
	end

	local charts = array()
	--% 假定ns难度序列是主难度序列的前缀
	for idx, tag in ipairs(colTags) do
		local chart = {}
		charts:insert(chart)
		local diff = song.difficulties[idx]

		local class = ({[0] = 'PST', 'PRS', 'FTR', 'BYD', 'ETR'})[diff.ratingClass]
		chart.display = ('<span class="text-%s">[%s]</span>'):format(lang:lc(class), tag)
		addCategory(class .. chart.rating .. '级曲目')
		local function chartBasic(df, vd, s)
			chart['rating' .. s] = args[tag .. '等级' .. s] or (df.rating .. (df.ratingPlus and '+' or ''))
			chart['note' .. s] = args[tag .. 'Note' .. s]
			chart['vdOverride' .. s] = vdValidation(args[tag .. '更新版本' .. s], args[tag .. '更新时间' .. s])
			if df.date and not chart['vdOverride' .. s] then notice.vd = true end
			chart['vdOverride' .. s] = chart['vdOverride' .. s] or vd
		end

		chartBasic(diff, vd, '')
		if not chart.note then notice.note = true end

		chart.designer = args[tag .. 'Note编写'] or args['note编写'] or diff.chartDesigner
		chart.bgOverride = args[tag .. '背景'] or diff.bg
		if chart.bgOverride then addCategory(bgCatF:format(chart.bgOverride)) end
		chart.bgOverride = chart.bgOverride or bg
		if diff.title_localized then header:newline():wikitext(diff.title_localized.en, ' ', chart.display) end
		local diffNS = sns.difficulties[idx]
		if diffNS then
			-- 仅移动版
			chartBasic(diffNS, vdNS, 'NS')
			if diffNS.has_controller_alt_chart then
				notice.alt = true
				if not chart.noteNS then notice.note = true end
			end
		end
	end
	main:tag 'div':addClass 'gc-1 bg-c':wikitext '谱面信息'
	main:tag 'div':addClass 'bg-c':wikitext '难度'
	for _, c in ipairs(charts) do
		main:tag 'div':wikitext(c.display)
	end
	main:tag 'div':addClass 'bg-c':wikitext '等级'
	for _, c in ipairs(charts) do
		main:tag 'div':wikitext(c.rating)
	end
	main:tag 'div':addClass 'bg-c':wikitext 'note数量'
	for _, c in ipairs(charts) do
		main:tag 'div':wikitext(c.note)
	end
	main:tag 'div':addClass 'bg-c':wikitext '谱面设计'
	for _, tp in ipairs(merge(charts, 'designer')) do
		local data, len = unpack(tp)
		main:tag 'div':addClass(span(len)):wikitext(data)
	end
	if platCode == 3 then
		main:tag 'div':addClass 'bg-c':wikitext '等级NS'
		for _, c in ipairs(charts) do
			main:tag 'div':wikitext(c.ratingNS)
		end
	end
	if notice.alt then
		addCategory '多模式谱面有差异的曲目'
		main:tag 'div':addClass 'bg-c':wikitext 'note数量<br>(Joy-Con)'
		for _, c in ipairs(charts) do
			main:tag 'div':wikitext(c.noteNS)
		end
	end
	main:tag 'div':addClass 'bg-c':wikitext '背景'
	for _, tp in ipairs(merge(charts, 'bgOverride')) do
		local data, len = unpack(tp)
		main:tag 'div':addClass(span(len)):wikitext(data and bgLinkF:format(data))
	end


	main:tag 'div':addClass 'bg-c':css(platCode == 3 and {gridRow = 'span 2'} or {}):wikitext '更新时间'
	for _, tp in ipairs(merge(charts, 'vdOverride')) do
		local data, len = unpack(tp)
		dateCov(main:tag 'div':addClass(span(len)), data, '移动版')
	end
	if platCode == 3 then
		for _, tp in ipairs(merge(charts, 'vdOverrideNS')) do
			local data, len = unpack(tp)
			dateCov(main:tag 'div':addClass(span(len)), data, 'NS版')
		end
	end

	local noticeText = ''
	for _, v in ipairs {
		{'data', '在Songlist中无法检查到此曲目。请尝试更新[[模板:Songlist]],检查页面名或填写正确的<code>曲名</code>参数。'},
		{'duration', '此模板缺少<code>时长</code>参数,此参数无法自动读取。'},
		{'pack', '未更新Packlist。曲目信息模板无法进行曲包分类。'},
		{'vd', '此模板的更新版本是未完整状态。请添加<code>更新版本</code>与<code>更新时间</code>参数。'},
		{'note', '此模板缺少某种<code>Note</code>参数,此参数无法自动读取。'},
	} do
		local msg, text = unpack(v)
		if notice[msg] then noticeText = noticeText .. text end
	end
	if noticeText ~= '' then
		noticeText = mw.getCurrentFrame():expandTemplate {title = 'Collapse', args = {['标题'] = '曲目信息模板提示信息', ['状态'] = '折叠',
			['标题文字方向'] = 'center', ['标题颜色'] = '#dddddd',
			['内容颜色'] = '#eeeeee', ['内容样式'] = 'width:800px',
			['style'] = 'display:table;width:200px', ['class'] = 'nomobile',
			['内容'] = noticeText}}
		category:add '缺少参数的曲目信息模板'
	end
	return tostring(box) .. notice .. (args['nocat'] and '' or table.concat(category))
end

function p.main(frame)
	local args = getArgs(frame)
	return auto(args)
end

return p