2,525
次編輯
小 (调整) |
小 (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 | local bgLinkF = '[[:分类:采用%s背景的曲目|%s]]' | ||
local | local bgCatF = '采用%s背景的曲目' | ||
local | 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 | 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 | end | ||
local function span(len) if len > 1 then return 'span-' .. len end end | |||
-- .container | |||
-- .img-tab#tab-a | |||
local | -- .img-tab-part.{cls} * n | ||
for | -- {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 | end | ||
return | return container | ||
end | end | ||
local function getImage(args, song) | |||
local | 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 | end | ||
local function tabCustom(args) | |||
local | local i = 1 | ||
local | local res = array() | ||
while args['tab' .. i] do | |||
res:insert {mw.ustring.match(args['tab' .. i], '([^/]*)/([^/]*)/([^/]*)/(.*)')} | |||
i = i + 1 | |||
end | end | ||
return res, args['默认图片序号'] | |||
end | end | ||
local function | local function merge(charts, field) | ||
local res = | local res = array() | ||
for _, | 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 | local function getSet(sm, sns) | ||
local res = { | --% 要求名字相同 | ||
local qm, qns = mad.packQueryWrap(sm and sm.set, 'mobile'), mad.packQueryWrap(sns and sns.set, 'ns') | |||
return | 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 | |||
local artist = args['编曲'] or args['曲师'] or song.artist | |||
local | if not set then notice.pack = true end | ||
for _, | -- addCategory %set曲包曲目 | ||
local | local duration = args['时长'] | ||
for | 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 | 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) | |||
for | end | ||
main:tag 'div':addClass 'bg-c':wikitext '等级' | |||
for _, c in ipairs(charts) do | |||
local | 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 | ||
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 | |||
for | local data, len = unpack(tp) | ||
local | 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 | ||
end | |||
end | |||
local | local noticeText = '' | ||
for _, v in ipairs { | |||
{'data', '在Songlist中无法检查到此曲目。请尝试更新[[模板:Songlist]],检查页面名或填写正确的<code>曲名</code>参数。'}, | |||
if | {'duration', '此模板缺少<code>时长</code>参数,此参数无法自动读取。'}, | ||
{'pack', '未更新Packlist。曲目信息模板无法进行曲包分类。'}, | |||
table | {'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 | end | ||
return tostring(box) .. notice .. (args['nocat'] and '' or table.concat(category)) | |||
end | |||
return | function p.main(frame) | ||
local args = getArgs(frame) | |||
return auto(args) | |||
end | end | ||
return p | return p |
次編輯