Skip to content

Instantly share code, notes, and snippets.

@Castux
Last active January 16, 2023 08:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Castux/57330993c00b009b9184042eb0d66f94 to your computer and use it in GitHub Desktop.
Save Castux/57330993c00b009b9184042eb0d66f94 to your computer and use it in GitHub Desktop.
local function parse_changes(meta_dir)
local find_cmd = string.format([[cat `find %s \( -name '*.changes' ! -name '_*' \)`]], meta_dir)
local months = {}
for line in io.popen(find_cmd):lines() do
local ts, kind = line:match "^(%d+)\t%S+\t(%w+)"
if line:match "Page moved" then
kind = "M"
elseif kind == "e" or kind == "R" then
kind = "E"
end
local t = os.date("*t", ts)
local key = string.format("%d-%02d", t.year, t.month)
if not months[key] then
months[key] = {}
end
if not months[key][kind] then
months[key][kind] = 0
end
months[key][kind] = months[key][kind] + 1
end
local flat = {}
for month, data in pairs(months) do
data.month = month
table.insert(flat, data)
end
table.sort(flat, function(a,b) return a.month < b.month end)
return flat
end
local kinds = {
C = "Pages created",
D = "Pages deleted",
M = "Pages moved",
E = "Page edits"
}
local kinds_short = {"C", "E", "M", "D"}
local function format_table(months)
local lines = {}
-- Headers
local header_line = "^ Month ^ "
for _,v in ipairs(kinds_short) do
header_line = header_line .. kinds[v] .. " ^ "
end
table.insert(lines, header_line)
-- Data
for _,data in ipairs(months) do
local line = "| " .. data.month .. " | "
for _,k in ipairs(kinds_short) do
line = line .. (data[k] or 0) .. " | "
end
table.insert(lines, line)
end
return table.concat(lines, "\n")
end
local function format_graph(months)
local json = require "json"
local labels = {}
local datasets = {}
for i,k in ipairs(kinds_short) do
datasets[i] = {
label = kinds[k],
data = {}
}
end
for _,month in ipairs(months) do
table.insert(labels, month.month)
for i,k in ipairs(kinds_short) do
table.insert(datasets[i].data, month[k] or 0)
end
end
local chart = {
type = "bar",
data = {
labels = labels,
datasets = datasets
},
options = {
scales = {
y = {
beginAtZero = true,
stacked = true
},
x = {
stacked = true
}
}
}
}
return json.encode(chart)
end
local template = [[
====== Wiki contributions statistics ======
<html>
<div>
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
const ctx = document.getElementById('myChart');
new Chart(ctx, %s);
</script>
</html>
%s
]]
local function write_page(meta_dir, out_path)
local data = parse_changes(meta_dir)
local table = format_table(data)
local chart = format_graph(data)
local f = io.open(out_path, "w")
f:write(string.format(template, chart, table))
f:close()
end
local function main()
if #arg ~= 2 then
error "Usage: lua make_stats.lua <meta_dir> <out_path>"
end
local meta_dir = arg[1]
local out_path = arg[2]
print("Meta dir:", meta_dir)
print("Out path:", out_path)
write_page(meta_dir, out_path)
end
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment