Module:Sandbox/Mathglot/Xviews

-- HELPER FUNCTIONS --
local function notblank(v) return (v or '' ) ~= '' end
local function ifblank(v, alt1, alt2) return notblank(v) and v or (notblank(alt1) and alt1 or alt2) end
local function red(v) return '<span style="color: red;">' .. v .. '</span>' end
local function getContent(page) return string.gsub(mw.title.new(page).content, '^Date,"[^"]+"', '') end
local function diffDays(dargs)
	return require('Module:diff days')['diff_days'](
		mw.getCurrentFrame():newChild{ title = 'Template:Diff_days', args = dargs }
	)
end
local showTimeLine = require('Module:Horizontal timeline')._showTimeLine
local Text = require('Module:Text').Text()

-- EXPORTED CONSTANTS --
local p = {
	gAGING = function() return 7 end,  --global for representing the age in days after which a pageviews file, and any chart based on it, is no longer fresh and should be updated. Charts are still displayed for articles with aging pageviews files; when the pageviews file reaches gSTALE, the chart is no longer displayed.
	gCOUNT = function() return 75 end, --global for representing the default number of days to display in the chart; overridable with param {{para|ct}}.
	gSTALE = function() return 30 end, --global for representing the age in days after which a pageviews file, and any chart based on it, becomes stale and no longer appropriate for display on a Talk page. Stale pages should have their pageviews file updated.
}

-- TEMPLATE FUNCTIONS --
function p._xviews(args)														-- {{User:Mathglot/sandbox/Templates/Xviews}}
	-- args contains stale, days, ct, log, and mode
	local page = ifblank(args[1], mw.title.getCurrentTitle().fullText .. '/pageviews')
	if mw.title.new(page).exists then
		local stale = tonumber(ifblank(args.stale, p.gSTALE()))
		if tonumber(p._age(page)) > stale then --stale:
			return red(mw.ustring.format(
				'The pageviews file [[%s]] is more than %d days old; please see [[User:Mathglot/sandbox/Templates/Xviews#Instructions|Instructions]].',
				page, stale
			))
		else --not stale:
			return p._xvmain(page, {ct = ifblank(args.days, args.ct, p.gCOUNT())}) ..
				((notblank(args.log) or notblank(args.mode)) and '' or p._xAxis(page, {})) -- p._xAxis() doesn't handle log values or vertical bars yet
		end
	else
		return red('Missing required pageviews file.') ..
			' See [[User:Mathglot/sandbox/Templates/Xviews#Instructions|Instructions]].'
	end
	
end
function p.xviews(frame)
	return p._xviews(frame.args)
end
	
function p._age(page)															-- {{User:Mathglot/sandbox/Templates/Xviews/age}}
	local nthview = p._nthView(page, p._viewCount(page))
	nthview = Text.split(nthview, ':', true)[1]
	return diffDays({nthview, mw.getContentLanguage():formatDate('j F Y'), precision=0})
end
function p.age(frame)
	return p._age(ifblank(frame.args[1] or 'Talk:Liberation of France/pageviews'))
end

function p._latest(page)															-- {{User:Mathglot/sandbox/Templates/Xviews/age}}
	return Text.split(p._nthView(page, p._viewCount(page)), ':', true)[2]
end
function p.latest(frame)
	return p._latest(ifblank(frame.args[1] or 'Talk:Liberation of France/pageviews'))
end

function p._nthView(page, index)												-- {{User:Mathglot/sandbox/Templates/Xviews/nth view}}
	local content = string.gsub(getContent(page), '.?(202%d%-%d%d%-%d%d)%,?(%d+)', '%1:%2,')
	content = string.gsub(content, "^%s*,%s*(.-)%s*,$", "%1")
	local items = {}
    for item in string.gmatch(content, "([^,]+)") do
        table.insert(items, mw.text.trim(item))
    end
	index = tonumber(index)
    if index < 0 then
        index = #items + index + 1
    end
	return items[index]
end
function p.nthView(frame)
	return p._nthView(
		ifblank(frame.args[1] or 'Talk:Liberation of France/pageviews'),
		ifblank(frame.args[2] or 3)
	)
end

function p._viewCount(page)														-- {{User:Mathglot/sandbox/Templates/Xviews/view count}}
	local str = string.gsub(getContent(page), '.?202%d%-%d%d%-%d%d', '')
	str = string.gsub(str, ',', '', 1)
	-- Remove leading and trailing delimiters (along with any surrounding whitespace)
    str = str:gsub("^%s*,%s*", ""):gsub("%s*,%s*$", "")
	-- Normalize internal consecutive delimiters to a single delimiter (replace ",," with ",")
    str = str:gsub("%s*,%s*,%s*", ',')
    return select(2, str:gsub(',', '')) + 1
end
function p.viewCount(frame)
	return p._viewCount(ifblank(frame.args[1], 'Talk:Liberation of France/pageviews'))
end

function p._xvmain(page, xargs)													-- {{User:Mathglot/sandbox/Templates/Xviews/xvmain}}
	-- xargs contains ct, log, mode, and debug
	local output = {}
	local stop = p._viewCount(page)
	local start = stop - math.min(152, ifblank(xargs.ct, 93)) + 1
	local iargs = {
		page = page,
		max = p._maxViews(page),
		log = xargs.log, -- logarithmic scale (not implemented yet)
		mode = xargs.mode, -- bar display orientation  (mode=vert not implemented yet)
		debug = xargs.debug, -- set to non-empty for loop debug output emitted by p._itemBar()
	}
	for n = start, stop do
		iargs.n = n
		table.insert(output, p._itemBar(iargs))
	end
	return table.concat(output)
end
function p.xvmain(frame)
	local xargs = frame.args
	xargs.ct = ifblank(xargs.ct, 93)
	return p._xvmain(ifblank(xargs[1], 'Talk:Liberation of France/pageviews'), xargs)
end

function p._itemBar(iargs)														-- {{User:Mathglot/sandbox/Templates/Xviews/item bar}}
	-- iargs contains n, page, max, log, mode, and debug
	if iargs.debug then
		return mw.ustring.format("page=%s, n=%s, label=%s",
			ifblank(iargs.page, 'missing'),
			ifblank(iargs.n, 'missing'),
			ifblank(iargs.label, 'missing')
		)
	end
	local nthview = p._nthView(iargs.page, ifblank(iargs.n, 1))
	if not nthview then
		error("Error generating item bar for item #" .. ifblank(iargs.n, 1) .. ". Range may be invalid")
	end
	local val = Text.split(nthview, ':', true)[2]
	local width = val * 100 * 0.88 / p._maxViews(iargs.page)
	width = tonumber(string.format("%.2f", width))
	local label = p._xlabel(Text.split(nthview, ':', true)[1], 'y')
	return p._vbar(width, val, {label = label})
end
function p.itemBar(frame)
	local iargs = frame.args
	iargs.page = ifblank(iargs.page, 'Talk:House of the Dragon/pageviews')
	iargs.n = ifblank(iargs.n, 1)
	return p._itemBar(iargs)
end

function p._vbar(width, val, vargs)												-- {{User:Mathglot/sandbox/Templates/Xviews/vbar}}
	-- vargs contains label, label-style, thick, style, val, and val-style
	local ts =  mw.getCurrentFrame():extensionTag{
		name = 'templatestyles',
		args = {src = 'User:Mathglot/sandbox/Templates/Xviews/vbar/styles.css'}
	}
	local div = mw.html.create('div'):addClass('vbar')
	if notblank(vargs.label) then
		div:tag('span')
			:addClass('vbar-labelh')
			:cssText(ifblank(vargs['label-style']))
			:wikitext(vargs.label)
	end
	div:tag('span')
		:addClass('vbar-h')
		:attr('alt', 'Page views for (date) = (views).')
		:css('height', ifblank(vargs['thick']))
		:css('width', width .. '%')
		:cssText(ifblank(vargs.style))
	if notblank(val) then
		div:tag('span')
			:addClass('vbar-valh')
			:cssText(ifblank(vargs['val-style']))
			:wikitext(val)
	end
	return ts .. tostring(div)
end
function p.vbar(frame)
	local vargs = frame.args
	return p._vbar(ifblank(vargs[1], 75), ifblank(vargs[2], vargs.val, 2136), vargs)
end

function p._xlabel(date, bold01)												-- {{User:Mathglot/sandbox/Templates/Xviews/xlabel}}
	local replace = ((date:sub(-3) == '-01') and notblank(bold01)) and "'''%1'''" or "%1"
	return string.gsub(date, '20[23]%d%-(%d%d%-%d%d)', replace)
end
function p.xlabel(frame)
	return p._xlabel(ifblank(frame.date, '2024-06-01'), frame.bold01)
end

function p._minViews(page)														-- {{User:Mathglot/sandbox/Templates/Xviews/min views}}
	local views = nil
	local content = string.gsub(getContent(page), '.?202%d%-%d%d%-%d%d', '')
	for v in Text.gsplit(content, ',', true) do
		v = tonumber(v)
		if views == nil or (v and v < views) then
			views = v
		end
	end
	return views
end
function p.minViews(frame)
	return p._minViews(ifblank(frame.args[1], 'Talk:Liberation of France/pageviews'))
end

function p._maxViews(page)														-- {{User:Mathglot/sandbox/Templates/Xviews/max views}}
	local views = 0
	local content = string.gsub(getContent(page), '.?202%d%-%d%d%-%d%d', '')
	for v in Text.gsplit(content, ',', true) do
		v = tonumber(v)
		if (v and v > views) then views = v end
	end
	return views
end
function p.maxViews(frame)
	return p._maxViews(ifblank(frame.args[1], 'Talk:Liberation of France/pageviews'))
end

function p._xAxis(page, xargs)													-- {{User:Mathglot/sandbox/Templates/Xviews/x-axis}}
	-- xargs contains shift, caption, ff
	local div = mw.html.create('div')
		:css('margin', '-22px 0 0 ' .. ifblank(xargs.shift, '16px'))
		:wikitext(
			showTimeLine({
				caption = ifblank(xargs.caption, 'page views for ' .. mw.title.new(page).rootText),
				border = 'none',
				from = 0,
				to = p._maxViews(page),
				inc = tonumber(string.format("%.0f", ifblank(xargs.ff, 1.0) * p._maxViews(page)/100)) * 10,
				row1 = 'scale',
				['axis-nudge'] = '-0.8em',
				['axis-0'] = '<span style="padding-left:10px">0</span>'
			})
		)
	return tostring(div)
end
function p.xAxis(frame)
	return p._xArgs(ifblank(frame.args[1], 'Talk:Liberation of France/pageviews'), frame.args)
end

function p._summary(page, sargs)												-- {{User:Mathglot/sandbox/Templates/Xviews/summary}}
	-- sargs contains days
	page = ifblank(page, mw.title.getCurrentTitle().fullText .. '/pageviews')
	if not mw.title.new(page).exists then return '' end
	return 'Pageviews [[User:Mathglot/sandbox/Templates/Xviews/summary#Description|summary]]: ' ..
		'size=' .. p._viewCount(page) ..
		', age=' .. p._age(page) ..
		', days=' .. ifblank(sargs.days, p.gCOUNT()) ..
		', min=' .. p._minViews(page) ..
		', max=' .. p._maxViews(page) ..
		', latest=' .. p._latest(page)
end
function p.summary(frame)
	return p._summary(frame.args[1], frame.args)
end

function p._isStale(page, days)													-- {{User:Mathglot/sandbox/Templates/Xviews/is stale}}
	page = ifblank(page, mw.title.getCurrentTitle().fullText .. '/pageviews')
	if not mw.title.new(page).exists then return 'missing' end
	local age = tonumber(p._age(page))
	if age > tonumber(ifblank(days, p.gSTALE())) then return 'stale' end
	if age > tonumber(ifblank(days, p.gAGING())) then return 'aging' end
	return ''
end
function p.isStale(frame)
	return p._isStale(frame.args[1], frame.args[2])
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.