模組:PJ:VG/HOT/v2
外观
< Module:PJ:VG | HOT
--- [[Module:PJ:VG/HOT/v2]]
require("strict")
local getArgs = require("Module:Arguments").getArgs
local language = mw.language.getContentLanguage()
local p = {}
local grades = {
["典范"] = "fa",
["特色列表"] = "fl",
["甲"] = "a",
["甲级列表"] = "al",
["优良"] = "ga",
["乙上"] = "bplus",
["乙"] = "b",
["乙级列表"] = "bl",
["丙"] = "c",
["丙级列表"] = "cl",
["初"] = "start",
["列表"] = "list",
["小作品"] = "stub",
["小列表"] = "sl",
["未评"] = "unassessed",
}
local importance = {
["极高"] = "top",
["高"] = "high",
["中"] = "mid",
["低"] = "low",
["未知"] = "unknown",
}
-- Badges are enabled unless a project explicitly disables them.
local enabledBadges = {
class = {
["电子游戏/宝可梦工作组"] = false,
},
importance = {
["电子游戏/宝可梦工作组"] = false,
["电子游戏/我的世界"] = false, -- sic: no "工作组" suffix
["电子游戏/史克威尔艾尼克斯工作组"] = false,
["电子游戏/世嘉工作组"] = false,
["电子游戏/任天堂工作组"] = false,
["电子游戏/米哈游工作组"] = false,
},
}
local siteRankLabels = {
daily = "全站日榜第",
weekly = "全站周榜第",
monthly = "全站月榜第",
quarterly = "全站季度榜第",
yearly = "全站年榜第",
}
local function number(value)
if value == nil then
return "未知"
end
return language:formatNum(value)
end
local literal = mw.text.nowiki
local function date(value)
local iso = string.format(
"%04d-%02d-%02d", value[1], value[2], value[3]
)
local timestamp = os.time({
year = value[1],
month = value[2],
day = value[3],
hour = 0,
isdst = false,
})
local label = string.format(
"%d年%d月%d日", value[1], value[2], value[3]
)
return iso, timestamp, label
end
local function badge(parent, value, kind, lookup)
local label = value or (kind == "class" and "未评" or "未知")
local code = lookup[label]
local description = (kind == "class" and "质量:" or "重要度:")
.. label
local class = table.concat({
"vg-hot-badge",
"vg-hot-" .. kind,
"vg-hot-" .. kind .. "-" .. code,
}, " ")
parent:tag("span")
:addClass(class)
:attr("role", "img")
:attr("title", description)
:attr("aria-label", description)
end
local function articleLink(title)
return "[[:" .. literal(title) .. "]]"
end
local function trend(parent, rank, previous, limit)
if previous == nil then
parent:tag("span")
:addClass("vg-hot-trend vg-hot-trend-unknown")
:attr("title", "上期名次未知")
:wikitext("(—)")
return
elseif previous == -1 then
parent:tag("span")
:addClass("vg-hot-trend vg-hot-trend-surge vg-hot-trend-new")
:attr("role", "img")
:attr("title", "新条目")
:attr("aria-label", "新条目")
:wikitext("New")
return
end
local delta = previous - rank
if delta == 0 then
return
end
local style = delta > 0 and "rise" or "fall"
if delta >= limit then
style = "surge"
end
local places = math.abs(delta)
local shown = delta > 0 and places >= 1000 and "999+"
or number(places)
local label = "上期第" .. number(previous) .. "名"
parent:tag("span")
:addClass("vg-hot-trend vg-hot-trend-" .. style)
:attr("role", "img")
:attr("title", label)
:attr("aria-label", label)
:wikitext(shown)
end
local function views(parent, item, metadata, period)
local total = parent:tag("span"):addClass("vg-hot-total")
if item.site_rank ~= nil then
local prefix = siteRankLabels[metadata.duration] or "全站榜第"
local label = prefix .. number(item.site_rank) .. "名"
total:addClass("vg-hot-site-top"):attr("title", label)
end
if item.views == nil then
total:wikitext("未知")
else
local url = mw.uri.new("https://pageviews.wmcloud.org/")
url:extend({
project = "lib.yinfer.top",
platform = "all-access",
agent = "user",
redirects = 0,
start = period.start,
["end"] = period["end"],
pages = item.title,
})
total:wikitext(
"[" .. tostring(url) .. " " .. number(item.views) .. "]"
)
end
-- A daily average would repeat the total.
-- Longer periods retain their average.
if period.days > 1 then
local average = item.views
and math.floor(item.views / period.days) or nil
parent:tag("span")
:addClass("vg-hot-average")
:attr("title", "日均浏览量")
:wikitext("(" .. number(average) .. ")")
end
end
local function renderItem(list, item, metadata, period, limit)
local row = list:tag("li"):attr("value", item.rank)
if enabledBadges.class[metadata.project] ~= false then
badge(row, item.assessments[1], "class", grades)
end
if enabledBadges.importance[metadata.project] ~= false then
badge(row, item.assessments[2], "importance", importance)
end
row:wikitext(articleLink(item.title))
:tag("span")
:addClass("vg-hot-separator")
:wikitext(" — ")
views(row, item, metadata, period)
trend(row, item.rank, item.previous_rank, limit)
end
local function renderSummary(parent, metadata, period)
local summary = parent:tag("ol")
:addClass("vg-hot-summary")
:addClass("vg-hot-hlist")
local dates = summary:tag("li")
dates:tag("b"):wikitext("统计时间:")
dates:wikitext(period.label)
if period.days > 1 then
dates:wikitext("<small>(计" .. number(period.days) .. "日)</small>")
end
local articles = summary:tag("li")
articles:tag("b"):wikitext("总条目数:")
articles:wikitext(number(metadata.total_pages) .. "篇")
local views = summary:tag("li")
views:tag("b"):wikitext("总浏览量:")
views:wikitext(number(metadata.total_views) .. "次")
if period.days > 1 then
local average = metadata.total_views
and math.floor(metadata.total_views / period.days) or nil
views:tag("small")
:wikitext("(日均" .. number(average) .. "次)")
end
end
function p.main(frame)
local args = getArgs(frame)
return p._main(args)
end
-- Decode bot-generated JSON: arrays become one-based sequences.
-- Null keys vanish.
function p._main(args)
local data = mw.text.jsonDecode(args.data)
local metadata = data.metadata
local start, startTime, startLabel = date(metadata.start)
local finish, finishTime, finishLabel = date(metadata["end"])
local period = {
start = start,
["end"] = finish,
days = os.difftime(finishTime, startTime) / 86400 + 1,
label = start == finish and startLabel
or startLabel .. "—" .. finishLabel,
}
local root = mw.html.create("div"):addClass("plainlinks")
renderSummary(root, metadata, period)
local list = root:tag("ol"):addClass("vg-hot-list")
for _, item in ipairs(data.items) do
renderItem(list, item, metadata, period, #data.items)
end
local styles = mw.getCurrentFrame():extensionTag(
"templatestyles", "", { src = "Module:PJ:VG/HOT/v2/styles.css" }
)
return styles .. tostring(root)
end
return p