Module:MasterGunner
Appearance
| This module is rated as beta. It is considered ready for widespread use, but as it is still relatively new, it should be applied with some caution to ensure results are as expected. |
Usage
[edit]{{#invoke:MasterGunner|GunnerBox}}
Please see {{Template:MasterGunner}} for example usage
-- 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%%" | ← #%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 →<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