ਮੌਡਿਊਲ:Monthly Challenge statistics
ਦਿੱਖ
Logic for {{Monthly Challenge statistics}}
--[=[
Statistics for data using the Monthly Challenge format.
There are two data sources:
* daily data, which provides _day-by-day_ total counts
* the core PRP Lua module, which provides direct _per-index_ counts
]=]
require('strict')
local p = {} --p stands for package
local getArgs = require('Module:Arguments').getArgs
-- ProofreadPage core module
local proofreadPage = require('mw.ext.proofreadPage')
-- Default data prefixes
local dDataPrefix = "Module:Monthly Challenge daily stats/data/"
local workDataPrefix = "Module:Monthly Challenge/data/"
local function length(arr)
if arr == nil then
return 0
end
local count = 0
for k, v in pairs(arr) do
count = count + 1
end
return count
end
--[=[
Calculate "processed" pages for a given stats dump
* validated is double because it includes a prior proofread step (otherwise
validating is a zero sum, as q3 loses one, and q4 gains one)
]=]
local function getProcessed(t)
return t.q0 + t.q3 + (t.q4 * 2)
end
local function getProofread(t)
return t.q3
end
local function getComplete(t)
return t.q0 + t.q4
end
local function getIncomplete(t)
return t.count - (t.q0 + t.q4)
end
--[=[
Get a list of works in a given month's data
]=]
local function getMonthWorks(monthData)
local works = {}
-- If asked for a bum date, monthData will be empty.
if monthData.works ~= nil then
for age, tab in pairs(monthData.works) do
for index, _ in pairs(tab) do
table.insert(works, proofreadPage.newIndex(index))
end
end
end
return works
end
--[=[
Get the number of works in the MC data list
]=]
local function getNumberOfWorks(monthData)
return #getMonthWorks(monthData)
end
--[=[
Get the total number of pages of all indexes in the month
]=]
local function getTotalPages(monthData)
local total = 0
local works = getMonthWorks( monthData )
for _, work in pairs( works ) do
total = total + work.pageCount
end
return total
end
local function getDailyUplifts(dData, excludeLastDay)
local uplifts = {
total = {
processed = 0,
proofread = 0,
complete = 0
},
days = {}
}
-- guard against totally bogus/missing input data
if dData == nil or dData.days == nil or dData.days[0] == nil then
return uplifts
end
local untilDay
if not untilDay then
-- includes 0 and today
local daysAvailable = length(dData.days)
untilDay = length(dData.days) - 1
end
if excludeLastDay and untilDay > 1 then
untilDay = untilDay - 1
end
local last = {
processed = getProcessed(dData.days[0]),
proofread = getProofread(dData.days[0]),
complete = getComplete(dData.days[0])
}
for day = 1, untilDay do
local day_data = dData.days[day]
local day_stats = {
processed = 0,
proofread = 0,
complete = 0
}
if day_data then
day_stats.processed = getProcessed(day_data) - last.processed
day_stats.proofread = getProofread(day_data) - last.proofread
day_stats.complete = getComplete(day_data) - last.complete
end
last.processed = last.processed + day_stats.processed
last.proofread = last.proofread + day_stats.proofread
last.complete = last.complete + day_stats.complete
table.insert(uplifts.days, day_stats)
uplifts.total.processed = uplifts.total.processed + day_stats.processed
uplifts.total.proofread = uplifts.total.proofread + day_stats.proofread
uplifts.total.complete = uplifts.total.complete + day_stats.complete
end
return uplifts
end
local function getMeans(uplifts)
local n = length(uplifts.days)
if n == 0 then
return {
processed = 0,
proofread = 0,
complete = 0,
}
end
return {
processed = uplifts.total.processed / n,
proofread = uplifts.total.proofread / n,
complete = uplifts.total.complete / n,
}
end
--[=[
Load data from dated page and return it.
Encapsulates load and error handling mechanics for multiple different data.
]=]
local function getData(prefix, year, month)
local statsPage = prefix .. string.format('%d-%02d', year, month)
local success, data = pcall(mw.loadData, statsPage)
if success ~= true then
-- TODO: add a tracking cat
return {}
end
return data
end
--[=[
Function docs
]=]
function p.statistics(frame)
local args = getArgs(frame)
local year = tonumber(args.year)
local month = tonumber(args.month)
local dData = getData(dDataPrefix, year, month)
local workData = getData(workDataPrefix, year, month)
local excludeToday = args.exclude_today
local txt = args.format
txt = txt:gsub('@num_works@', function()
return getNumberOfWorks(workData)
end)
txt = txt:gsub('@count_all_pages@', function()
return getTotalPages(workData)
end)
txt = txt:gsub('@mean_processed_to_date@', function()
local uplifts = getDailyUplifts(dData, excludeToday)
local monthlyMeans = getMeans(uplifts)
return math.floor(monthlyMeans.processed + 0.5)
end)
txt = txt:gsub('@processed_this_month@', function()
local uplifts = getDailyUplifts(dData, excludeToday)
return uplifts.total.processed
end)
txt = txt:gsub('@processed_yesterday@', function()
local timeNow = os.date("*t")
timeNow.day = timeNow.day - 1
local timeYesterday = os.date("*t", os.time(timeNow))
local yestData = dData
if not (timeYesterday.month == month and timeYesterday.year == year) then
yestData = getData(dDataPrefix, timeYesterday.year, timeYesterday.month)
end
local uplifts = getDailyUplifts(yestData, false)
if uplifts.days[timeYesterday.day] then
return uplifts.days[timeYesterday.day].processed
end
return 0
end)
txt = txt:gsub('@target_pages@', function()
return workData.target
end)
txt = txt:gsub('@processed_percent@', function()
local uplifts = getDailyUplifts(dData, excludeToday)
if workData.target == nil or workData.target <= 0 then
return '0'
end
return string.format("%.1f", 100 * uplifts.total.processed / workData.target)
end)
return txt
end
return p