Edge Rewrite
// HTMLRewriter · presentation

This page was redesigned at the edge.

Cloudflare fetched the original article and streamed it through HTMLRewriter to apply an entirely new visual system without rebuilding the source page.

Jump to content

Module:MasterGunner

From Wikipedia, the free encyclopedia

-- South African Master Gunner module
-- Data: [[Module:MasterGunner/data]]
-- Template: [[Template:MasterGunner]]
-- Initial code by John Dovey (13 April 2023) [[User:BoonDock]]

require('strict')
local p = {}
local data = mw.loadData('Module:MasterGunner/data')
local getArgs = require('Module:Arguments').getArgs

local LIST_PAGE = 'Master Gunners of the South African Army'
local BADGE_FILE = 'SANDF Arty Master Gunner badge embossed.png'
local ERROR_CAT = '' -- avoid redlinked tracking cats; errors use class="error"

local function trim(s)
	if s == nil then
		return ''
	end
	return mw.text.trim(tostring(s))
end

local function isUnknown(record)
	if not record then
		return true
	end
	local surname = trim(record.Surname)
	return surname == '' or surname == 'Unknown'
end

-- Sorted list of data keys by numeric Code
local function sortedKeys(includeUnknown)
	local keys = {}
	for key, record in pairs(data) do
		if includeUnknown or not isUnknown(record) then
			keys[#keys + 1] = key
		end
	end
	local function sortKey(code)
		-- Grandfathered Larkhill awards use 1000+ codes; list them first chronologically
		if code and code >= 1000 then
			return code - 10000
		end
		return code or 0
	end
	table.sort(keys, function(a, b)
		local ca = sortKey(data[a].Code)
		local cb = sortKey(data[b].Code)
		if ca == cb then
			return a < b
		end
		return ca < cb
	end)
	return keys
end

local function adjacentKey(codeNum, direction)
	local keys = sortedKeys(false)
	local idx
	for i, key in ipairs(keys) do
		if data[key].Code == codeNum then
			idx = i
			break
		end
	end
	if not idx then
		return nil
	end
	return keys[idx + direction]
end

function p.GetGunner(gunnercode)
	local record = data[gunnercode]
	if isUnknown(record) then
		return "''Unknown''"
	end
	local rank = trim(record.Rank)
	local name = mw.text.trim(trim(record.FirstName) .. ' ' .. trim(record.Surname))
	local wiki = trim(record.WikiPage)
	local nameHtml
	if wiki == '' then
		nameHtml = name
	else
		nameHtml = string.format('[[%s|%s]]', wiki, name)
	end
	if rank ~= '' then
		return rank .. '<br />' .. nameHtml
	end
	return nameHtml
end

function p.Gunner(frame)
	local args = getArgs(frame)
	local gunnercode = args.code
	if not gunnercode then
		return '<strong class="error">Error: No code specified</strong>' .. ERROR_CAT
	end
	local record = data[gunnercode]
	if not record then
		return string.format('<strong class="error">Error: code %s not found</strong>', gunnercode) .. ERROR_CAT
	end
	if isUnknown(record) then
		return string.format('%s: number %s (unknown / vacant)', gunnercode, tostring(record.Code))
	end
	return string.format(
		'%s: #%s — %s %s (%s)',
		gunnercode,
		tostring(record.Code),
		trim(record.FirstName),
		trim(record.Surname),
		trim(record.Year)
	)
end

function p.GunnerBox(frame)
	local args = getArgs(frame)
	local gunnercode = args.code
	local imagesize = args.imagesize or '150px'

	if not gunnercode then
		return '<strong class="error">Error: No <code>code</code> specified. Use the Gunner number preceded by an A, e.g. <code>code=A48</code>.</strong>' .. ERROR_CAT
	end

	local record = data[gunnercode]
	if not record then
		return string.format('<strong class="error">Error: code %s not found</strong>', gunnercode) .. ERROR_CAT
	end

	local float = args.float or 'none'
	local floatClass = ''
	if float == 'left' then
		floatClass = 'floatleft'
	elseif float == 'right' then
		floatClass = 'floatright'
	end

	local rows = {}
	local function add(line)
		rows[#rows + 1] = line
	end

	add('{| class="wikitable ' .. floatClass .. '" style="text-align:center; width:15em; font-size:90%"')
	add('|-')
	add('! colspan="2" style="background:#8B0000; color:white;" | Master Gunner #' .. tostring(record.Code))
	add('|-')
	add(string.format(
		'| colspan="2" | [[File:%s|border|%s|link=List of badges of the South African Army#Proficiency:_Master_Gunner|Master Gunner badge]]',
		BADGE_FILE,
		imagesize
	))
	add('|-')

	local nameCell = p.GetGunner(gunnercode)
	local post = trim(record.Post)
	local note = trim(record.Note)
	if post ~= '' then
		nameCell = nameCell .. frame:expandTemplate{ title = 'efn', args = { 'Post occupied when award was made: ' .. post } }
	end
	if note ~= '' then
		nameCell = nameCell .. frame:expandTemplate{ title = 'efn', args = { note } }
	end
	add('| colspan="2" | ' .. nameCell)
	add('|-')
	add(string.format('| colspan="2" | [[%s|Year]]: \'\'\'%s\'\'\'', LIST_PAGE, trim(record.Year)))

	local prevKey = adjacentKey(record.Code, -1)
	local nextKey = adjacentKey(record.Code, 1)
	add('|-')
	if prevKey then
		add(string.format('| style="text-align:left; font-size:85%%" | ←&nbsp;#%s<br />%s', tostring(data[prevKey].Code), p.GetGunner(prevKey)))
	else
		add('| style="text-align:left; font-size:85%" | ')
	end
	if nextKey then
		add(string.format('| style="text-align:right; font-size:85%%" | #%s&nbsp;→<br />%s', tostring(data[nextKey].Code), p.GetGunner(nextKey)))
	else
		add('| style="text-align:right; font-size:85%" | ')
	end
	add('|}')

	return table.concat(rows, '\n')
end

function p.GunnerTable(frame)
	local args = getArgs(frame)
	local showUnknown = args.showunknown == 'yes' or args.showUnknown == 'yes'

	local rows = {}
	local function add(line)
		rows[#rows + 1] = line
	end

	add('{| class="wikitable sortable"')
	add('|+ List of Master Gunners')
	add('|-')
	add('! Data key !! Number !! Rank !! Surname !! First names !! Post !! Year !! Notes')

	for _, key in ipairs(sortedKeys(showUnknown)) do
		local record = data[key]
		local unknown = isUnknown(record)
		if unknown then
			add('|- style="background:#f8f8f8; color:#555"')
		else
			add('|-')
		end
		add('| <code>' .. key .. '</code>')
		add('| data-sort-value="' .. tostring(record.Code or 0) .. '" | ' .. tostring(record.Code or ''))
		add('| ' .. trim(record.Rank))
		local surname = trim(record.Surname)
		local wiki = trim(record.WikiPage)
		if wiki ~= '' and not unknown then
			add(string.format('| [[%s|%s]]', wiki, surname))
		else
			add('| ' .. surname)
		end
		add('| ' .. trim(record.FirstName))
		local post = trim(record.Post)
		if post ~= '' then
			post = mw.ustring.gsub(post, ',', '<br />')
		end
		add('| ' .. post)
		add('| ' .. trim(record.Year))
		local note = trim(record.Note)
		if note ~= '' then
			add('| <small>' .. note .. '</small>')
		else
			add('|')
		end
	end
	add('|}')
	return table.concat(rows, '\n')
end

return p