Module:AlbumDonut
From Linkinpedia
More actions
Documentation for this module may be created at Module:AlbumDonut/doc
local p = {}
local chart = require("Module:Chart")
-- Album label and link overrides
local labelOverrides = {
["No4"] = "Nº4",
["HT EP"] = "Hybrid Theory EP",
["Tiny Music"] = "Tiny Music...Songs From The Vatican Gift Shop"
}
local linkOverrides = {
["Other"] = nil,
["No4"] = "No4",
["HT EP"] = "Hybrid Theory EP",
["Tiny Music"] = "Tiny Music...Songs From The Vatican Gift Shop"
}
-- Helpers
local function albumOf(frame, song)
return frame:expandTemplate{ title = "AlbumList", args = { song } }
end
local function albumColor(frame, key)
return frame:expandTemplate{ title = "AlbumColor", args = { key } }
end
-- Build one legend row (with collapsible song list)
local function legendRow(frame, albumKey, count, songs)
local color = albumColor(frame, albumKey)
local label = labelOverrides[albumKey] or albumKey
local link = linkOverrides[albumKey] or albumKey
local toggleId = mw.ustring.gsub(albumKey, "%s+", "")
-- label formatting
local linkText
if linkOverrides[albumKey] then
linkText = string.format("[[%s|<i>%s</i>]]", link, label)
else
linkText = "<i>" .. label .. "</i>"
end
-- row container
local row = mw.html.create("tr")
row:tag("td")
:css("width","6px")
:css("background-color", color)
row:tag("td")
:css("padding-left","0.5em")
:css("padding-right","0.5em")
:wikitext(linkText)
row:tag("td")
:wikitext(string.format(
'<div class="mw-customtoggle-%s">( <span style="color:var(--color-progressive)">%d</span> )</div>',
toggleId, count
))
-- collapsible song list
local songList = {}
for _,s in ipairs(songs) do
table.insert(songList, "<li><i>"..s.."</i></li>")
end
row:tag("td")
:wikitext(string.format(
'<div class="mw-collapsible mw-collapsed" id="mw-customcollapsible-%s">' ..
'<div class="mw-collapsible-content"><ul><small>%s</small></ul></div></div>',
toggleId, table.concat(songList,"\n")
))
return tostring(row)
end
function p.render(frame)
-- Gather songs from args
local songs = {}
for i=1,32 do
local s = frame.args["Song"..i]
if s and s ~= "" then table.insert(songs, s) end
local sx = frame.args["Song"..i.."x"]
if sx and sx ~= "" then table.insert(songs, sx) end
end
-- Count per album
local counts, songMap = {}, {}
for _,song in ipairs(songs) do
local album = albumOf(frame, song)
if album == "" then album = "Other" end
counts[album] = (counts[album] or 0) + 1
songMap[album] = songMap[album] or {}
table.insert(songMap[album], song)
end
-- Sort albums by count desc
local albums = {}
for k,v in pairs(counts) do table.insert(albums, { key=k, count=v }) end
table.sort(albums, function(a,b) return a.count > b.count end)
-- Build slices
local sliceStrings = {}
for _,a in ipairs(albums) do
local label = labelOverrides[a.key] or a.key
local color = albumColor(frame, a.key)
local link = linkOverrides[a.key] or (a.key ~= "Other" and a.key or "")
table.insert(sliceStrings, string.format("(%d:%s:%s:%s)", a.count, label, color, link or ""))
end
-- Chart
local chartSvg = chart["pie chart"]{
args = {
["radius"] = "100",
["inner percent"] = "70",
["slices"] = table.concat(sliceStrings, " ")
}
}
-- Legend
local legend = mw.html.create("table"):css("margin-top","0.5em")
for _,a in ipairs(albums) do
legend:wikitext(legendRow(frame, a.key, a.count, songMap[a.key] or {}))
end
return tostring(mw.html.create("div")
:css("padding","1em")
:wikitext(chartSvg .. tostring(legend)))
end
return p