Module:虚拟歌手外语排行榜/列表
来自Vocawiki
更多操作
此模块的文档可以在Module:虚拟歌手外语排行榜/列表/doc创建
local p = {}
local jsonEncode = mw.text.jsonEncode
local function trim(v)
if v == nil then return '' end
v = tostring(v)
return mw and mw.text and mw.text.trim and mw.text.trim(v) or (v:gsub('^%s+', ''):gsub('%s+$', ''))
end
local function toNumber(v)
return tonumber(trim(v)) or 0
end
local segmentColors = {
'#00B8C6','#60A5FA','#34D399','#FBBF24',
'#F87171','#A78BFA','#22D3EE','#4ADE80',
'#FB923C','#F472B6','#2DD4BF','#94A3B8',
'#C084FC','#38BDF8','#86EFAC','#FDBA74'
}
local function orderedArgs(frame)
local parent = frame:getParent()
local source = parent and parent.args or frame.args or {}
local args, i = {}, 1
while source[i] ~= nil do
args[#args + 1] = source[i]
i = i + 1
end
return args
end
local function parseArgs(frame)
local args = orderedArgs(frame)
local rawData = {}
local lastSong = ''
for i = 1, #args, 3 do
local currentSong = trim(args[i])
local startIssueArg = args[i + 1]
local endIssueArg = args[i + 2]
local song = currentSong ~= '' and currentSong or lastSong
if currentSong ~= '' then
lastSong = currentSong
end
if song == '' or startIssueArg == nil then break end
local startIssue = toNumber(startIssueArg)
if startIssue == 0 then break end
local endIssue = toNumber(endIssueArg)
if endIssue <= 0 or endIssue < startIssue then
endIssue = startIssue
end
local count = endIssue - startIssue + 1
local issues = count == 1 and ('#' .. startIssue) or ('#' .. startIssue .. '~#' .. endIssue)
rawData[#rawData + 1] = {
song = song,
count = count,
startIssue = tostring(startIssue),
issues = issues
}
end
return rawData
end
function p.chart(frame)
local parent = frame:getParent()
local args = parent and parent.args or frame.args
local rawData = parseArgs(frame)
if #rawData == 0 then return '' end
local dimName = trim(args.dimName) ~= '' and trim(args.dimName) or '歌曲'
local dimCount = trim(args.dimCount) ~= '' and trim(args.dimCount) or '次数'
local dimIssue = trim(args.dimIssue) ~= '' and trim(args.dimIssue) or '期数'
local xAxisName = trim(args.xAxisName) ~= '' and trim(args.xAxisName) or dimCount
local dimSegment = 'INTERNAL_SEGMENT'
local dimTotal = 'INTERNAL_TOTAL'
local totals = {}
for _, item in ipairs(rawData) do
totals[item.song] = (totals[item.song] or 0) + item.count
end
local songCount = 0
for _ in pairs(totals) do songCount = songCount + 1 end
local source = {}
local segmentCounters = {}
local maxSegment = 0
for _, item in ipairs(rawData) do
local song = item.song
local segmentNum = (segmentCounters[song] or 0) + 1
segmentCounters[song] = segmentNum
maxSegment = math.max(maxSegment, segmentNum)
source[#source + 1] = { song, tostring(segmentNum), item.count, item.issues, totals[song] }
end
local datasets = {
{ id = 'source', dimensions = { dimName, dimSegment, dimCount, dimIssue, dimTotal }, source = source },
{ id = 'sorted_source', fromDatasetId = 'source', transform = { type = 'sort', config = { dimension = dimTotal, order = 'desc' } } },
{ id = 'unique_source', fromDatasetId = 'sorted_source', transform = { type = 'filter', config = { dimension = dimSegment, value = '1' } } }
}
for idx = 1, maxSegment do
datasets[#datasets + 1] = {
id = 'seg' .. idx,
fromDatasetId = 'sorted_source',
transform = { type = 'filter', config = { dimension = dimSegment, value = tostring(idx) } }
}
end
local series = {}
for idx = 1, maxSegment do
local colorIndex = ((idx - 1) % #segmentColors) + 1
series[#series + 1] = {
type = 'bar',
stack = 'total',
datasetId = 'seg' .. idx,
itemStyle = { color = segmentColors[colorIndex] },
encode = { x = dimCount, y = dimName, tooltip = { dimCount, dimIssue } }
}
end
series[#series + 1] = {
type = 'scatter',
datasetId = 'unique_source',
symbolSize = 0,
hoverAnimation = false,
itemStyle = { color = '#00B8C6' },
label = {
show = true,
position = 'right',
color = '#333333',
fontWeight = 'bold',
formatter = string.format('{@%s}', dimTotal),
fontSize = 12
},
encode = { x = dimTotal, y = dimName, tooltip = {dimTotal}, itemName = dimName }
}
local option = {
tooltip = { trigger = 'item', confine = true },
legend = { show = false },
grid = { left = '20%', top = 20, bottom = 20 },
xAxis = { type = 'value', name = xAxisName },
yAxis = { type = 'category', inverse = true, axisLabel = { fontSize = 12 },name = dimName,nameLocation = 'start',nameGap = 5},
dataset = datasets,
series = series
}
local width = trim(args.width) ~= '' and trim(args.width) or '1000'
local calculatedHeight = 80 + (songCount * 15)
return frame:expandTemplate{ title = 'Echart', args = {
data = jsonEncode(option),
height = calculatedHeight,
width = width
}}
end
return p