Module:Daily proofreading stats table

--[=[ Module description ]=] require('strict')

local p = {} --p stands for package

local getArgs = require('Module:Arguments').getArgs local yesno = require('Module:Yesno')

local lowerLimit = 100 local upperLimit = 200

local function get_days_in_month(month, year) local days_in_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } local d = days_in_month[month] -- check for leap year if (month == 2) then if (math.mod(year,4) == 0) then if (math.mod(year,100) == 0) then if (math.mod(year,400) == 0) then d = 29 end else d = 29 end end end return d end

-- calculate "processed" pages for a given stats dump -- validated is double because it includes a prior proofread step local function get_processed(t) return t.q0 + t.q3 + (t.q4 * 2) end

local function add_note_row(tab, colspan, content, classes) local row = tab:tag('tr') row:tag('td') :attr('colspan', colspan) :wikitext(content) if classes then row:addClass(classes) end row:addClass('wst-daily-stats-note-row') end

local function add_col_header(tr, content, title) local th = tr:tag('th') :wikitext(content) :attr('scope', 'col') if title then th:attr('title', title) end end

--[=[ Function docs ]=] function p.table(frame) local args = getArgs(frame) local t = mw.html.create('table') :addClass('wst-daily-stats') local ok, data = pcall(mw.loadData, args.source) local year = tonumber(args.year) local month = tonumber(args.month) local num_cols = 5 t:tag('caption') :wikitext("Daily statistics") add_note_row(t, num_cols,		"Day under " .. lowerLimit,		'wst-daily-stats-under-target') add_note_row(t, num_cols,		"Day over " .. upperLimit,		'wst-daily-stats-over-target') local tr = t:tag('tr') add_col_header(t, 'Day') add_col_header(t, 'P', 'Pages proofread on this day') add_col_header(t, 'V', 'Pages validated on this day') add_col_header(t, 'Pages', 'Pages proofread, validated or marked without text on this day') add_col_header(t, 'Total', 'Pages proofread, validated or marked without text since the start of the month')

local now = os.date("!*t")

local max_day = now.day;

if yesno(args.include_today) then max_day = max_day + 1 end

local totals = { proofread = 0, validated = 0, processed = 0, }	local avg_totals = { proofread = 0, validated = 0, processed = 0, num_days = 0, }	if (now.year > year) or (now.year == year and now.month > month) then -- the data is in the past, show all days max_day = 100 elseif (now.year < year) or (now.month < month) then -- in the future max_day = 0; end local last; if data and data.days then -- data is present last = data.days[0]; else -- data is missing max_day = 0 end

local day_data for day = 1, get_days_in_month(month, year) do		if data.days then day_data = data.days[day] end

local processed = 0 local diff = 0 local proofread = 0 local validated = 0 local last_proc = 0 if last then last_proc = get_processed(last) end if day_data then processed = get_processed(day_data) diff = processed - last_proc validated = day_data.q4 - (last.q4 or 0) -- every validated page also "steals" a proofread page proofread = day_data.q3 - (last.q3 or 0) + validated totals.proofread = totals.proofread + proofread totals.validated = totals.validated + validated end totals.processed = totals.processed + diff tr = t:tag('tr') :addClass('wst-daily-stats-daydata') tr:tag('td') :wikitext(day) :attr('data-day', day)

if day < max_day then if args.include_today and day == max_day - 1 then tr:addClass('wst-daily-stats-in-progress') :attr('title', 'This day is not yet complete, these are the most recent statistics.') else -- include the day in the averages avg_totals.processed = totals.processed avg_totals.proofread = totals.proofread avg_totals.validated = totals.validated avg_totals.num_days = avg_totals.num_days + 1 end tr:tag('td') :wikitext(proofread) tr:tag('td') :wikitext(validated) tr:tag('td') :wikitext(diff) -- month-to-date total tr:tag('td') :wikitext(totals.processed) if day_data and diff < lowerLimit then tr:addClass('wst-daily-stats-under-target') elseif diff > upperLimit then tr:addClass('wst-daily-stats-over-target') end if day_data == nil then tr:addClass('wst-daily-stats-missing-data') end else -- add dummy table cells tr:tag('td') tr:tag('td') tr:addClass('wst-daily-stats-empty') end

last = day_data end

if avg_totals.num_days > 0 then -- add the averages tr = t:tag('tr') :addClass('wst-daily-stats-average')

tr:tag( 'td' ) :wikitext( 'Avg.' ) :attr( 'title', 'The average page counts for whole days completed this month' ) tr:tag( 'td' ) :wikitext(string.format( '%d', ( avg_totals.proofread / avg_totals.num_days ) + 0.5 ) ) tr:tag( 'td' ) :wikitext(string.format( '%d', ( avg_totals.validated / avg_totals.num_days ) + 0.5 ) ) tr:tag( 'td' ) tr:tag( 'td' ) :wikitext(string.format( '%d', ( avg_totals.processed / avg_totals.num_days ) + 0.5 ) ) -- add the totals tr = t:tag('tr') :addClass( 'wst-daily-stats-total' ) tr:tag('td') :wikitext('Total') :attr( 'title', 'The total pages completed in each category this month' ) tr:tag('td') :wikitext(totals.proofread) tr:tag('td') :wikitext(totals.validated) tr:tag('td') tr:tag('td') :wikitext(totals.processed) end return t end

return p