Module:MilAward

require('strict')local p = {}local data = mw.loadData('Module:MilAward/data')local getArgs = require('Module:Arguments').getArgslocal GlobalTemplateArgs = '' -- define as global (to this module) variablefunction p.GraphData (frame)    -- This routine is simply to create the x and y data lines for the graph of number of entries poer country    -- It iterates through the data, counting the number of entries for each country and then     -- create two lines holding those values as comma seperated values    -- This function should geenerate only two lines containing the  data for the graph and     -- should be invoked at the correct place in the graph setup.    -- Create an empty local table called "StatCount"    local StatCount = {}        -- Iterate through the data in the table "data"    for code, record in pairs(data) do        local country = record.Country        -- Check if the country is already in StatCount        if StatCount[country] then            -- If it is, add one to the count            StatCount[country] = StatCount[country] + 1        else            -- If it isn't, add the country to the table with a value of 1            StatCount[country] = 1        end    end    local xGraphValues = "| x=" -- Create the start of the x values line for a graph    local yGraphValues = "| y=" -- Create the start of the y values line for a graph    -- Iterate through the StatCount table using pairs    for country, count in pairs(StatCount) do        xGraphValues = xGraphValues .. ", " .. country -- add the name of the country as a comma seperated value        yGraphValues = yGraphValues .. ", " .. count -- add the count for the country as a comma seperated value    end    local output =  " \n" .. xGraphValues .. " \n" .. yGraphValues .. "\n"    return outputendfunction p.Stats(frame)    -- Create an empty local table called "StatCount"    local StatCount = {}        -- Iterate through the data in the table "data"    for code, record in pairs(data) do        local country = record.Country        -- Check if the country is already in StatCount        if StatCount[country] then            -- If it is, add one to the count            StatCount[country] = StatCount[country] + 1        else            -- If it isn't, add the country to the table with a value of 1            StatCount[country] = 1        end    end    -- Create an empty table to store the wiki code rows    local wikiRows = {}local xGraphValues =''local yGraphValues =''    -- Iterate through the StatCount table using pairs    for country, count in pairs(StatCount) do        -- Add a row to the wikiRows table with the country and count data        table.insert(wikiRows, "|-\n|" .. country .. "||" .. count)         xGraphValues = xGraphValues .. ", " .. country         yGraphValues = yGraphValues .. ", " .. count    end    -- Create the wiki code for the table using the wikiRows table    local wikiCode = "{| class=\"wikitable sortable col2right\"\n|-\n! Country !! Count\n" .. table.concat(wikiRows, "\n") .. "\n|}"    local wikiCode = wikiCode .. " \n" .. xGraphValues .. " \n" .. yGraphValues .. "\n"    -- Return the wiki code    local tablist= p.PrintStats()    local output = wikiCode .. "\n\n" .. tablist    return outputendfunction p.PrintStats()    -- Convert key-value pairs into a list of {code, data[code]} pairs    local pairsList = {}    for code, values in pairs(data) do        table.insert(pairsList, {code, values})    end    -- Sort the list based on the "Description" field of each pair    table.sort(pairsList, function(a, b)        return a[2].Description < b[2].Description    end)    -- Generate wiki table code for the sorted list    local tableCode = "{| class=\"wikitable sortable\"\n"    tableCode = tableCode .. "|-\n"    tableCode = tableCode .. "! Code !! Old Code !! Description !! Country\n !! Postnom !! Ribbon !! Org\n"    for i, pair in ipairs(pairsList) do        local code, values = pair[1], pair[2]        local oldcode = values.Code or ""        local country = values.Country or ""        local description = values.Description or ""        local class = values.Class or ""        local postnom = values.PostNom or ""        local ribbonimage = values.RibbonImage or ""        local pagelink = values.PageLink or ""        local note = values.Note or ""        local org = values.Org or ""        tableCode = tableCode .. "|-\n"        tableCode = tableCode .. "|" .. code .. "\n"        if code == oldcode then        tableCode = tableCode .. "| \n"        else        tableCode = tableCode .. "|" .. oldcode .. "\n"        end        tableCode = tableCode .. "|[[" .. pagelink .. "|" .. description         if string.len(class) > 0 then        tableCode = tableCode .. "]] '''(" .. class .. ")'''"else        tableCode = tableCode .. "]]"        end        if string.len(note) > 0 then            tableCode = tableCode .. mw.getCurrentFrame():expandTemplate{ title = 'Efn', args = {note} } -- Note: Page needs {{notelist}}        --tableCode = tableCode .. " <sup>" .. note .. "</sup> "         end        tableCode = tableCode .. "\n"        tableCode = tableCode .. "|" .. country .. "\n"        tableCode = tableCode .. "|" .. postnom .. "\n"        tableCode = tableCode .. "|[[File:" .. ribbonimage .. "|x30px]]\n"        tableCode = tableCode .. "|" .. org .. "\n"    end    tableCode = tableCode .. "|}"    return tableCodeendfunction p.Display(frame)-- Take parameters out of the frame and pass them to p._Display(). Return the result.local templateArgs = getArgs(frame)--local templateArgs = frame.argslocal code = templateArgs[1] or 'None'local size = templateArgs[2] or "40px"local namedcode = templateArgs["code"]if namedcode then code = namedcodeendlocal namedsize = templateArgs["size"]if namedsize thensize = namedsizeendreturn p._Display(code, size)endfunction p._Display(code, size)    -- data is loaded globally        local output = ""            output = output .. " '''Found award with code''': " .. data[code].Code .. "<br />"            output = output .. "''Code'': " .. data[code].Code .. "<br />"            output = output .. "''Description'': " .. data[code].Description .. "<br />"            output = output .. "''Ribbon Image'': " .. data[code].RibbonImage .. "<br />"            output = output .. "''Post-Nominal'': " .. data[code].PostNom .. "<br />"            output = output .. "''Page Link'': " .. data[code].PageLink .. "<br />"            output = output .. "''Country'': " .. data[code].Country .. "<br />"    return outputendlocal function _Ribbon(code, size)local ribbonimage=data[code].RibbonImageif string.len(size) <1 then size="x12px" -- weasel code. Check that there is a value for size and if not, set the valueendif string.len(ribbonimage)<1 then  -- If there is no ribbonimage defined for the record, then assign a default one.ribbonimage = "NOT-AVAILABLE-RIBBON.svg"end    local output = "[[File:" .. ribbonimage .. "|".. size .. "|link=" .. data[code].PageLink .. "|" .. data[code].Description .. " ''" .. data[code].PostNom .. "''" .. "]]" -- .. " [[Category:MilAward Ribbon]]"    return outputendfunction p.Ribbon(frame)-- Function extracts the parameters from the frame (passed into the function)-- It checks that the first argument is not empty, and returns an error if solocal templateArgs = getArgs(frame)--local templateArgs = frame.argslocal code = templateArgs[1] or 'None'local size = templateArgs[2] or "x12px"    local namedcode = templateArgs["code"] -- Check for named argument "code" and overwrite the value in the local variable if it has a valueif namedcode then code = namedcodeendlocal namedsize = templateArgs["size"] -- Check for named argument "size" and overwrite the value in the local variable if it has a valueif namedsize thensize = namedsizeendif string.match(code, "%*") then -- The code field has asterisks in it. Raise an error-- code = string.gsub(code, "%*", "x")local output = '<span style="color:#d33"> Bad Code: <b>[' .. code .. ']</b>. Replace all * with x</span> [[Category:MilAward Error]]'return outputend -- End ifif not code or '' == code then-- return '<span style="color:#d33">Error: missing positional parameter 1</span>'return '<span style="color:#d33"> (Invalid Code: <b>' .. code .. '</b> )</span> [[Category:MilAward Error]]'end--local code = code:upper() -- DO NOT DO THIS. Code is case sensitive -- Converts the first argument to uppercaseif not data[code] then-- return '<span style="color:#d33">Error: invalid positional parameter 1: ' .. code .. '</span>'return '<span style="color:#d33"> (Code not found: <b>' .. code .. '</b> )</span> [[Category:MilAward Error]]'endreturn _Ribbon (code, size)endlocal function _RibbonDesc(code, size, country, norib, nocat, org)    -- This routine is where the data is structured for output     local output =''    if norib ~= "yes" then -- They do NOT want the ribbon to display if this is yes    output = output .. _Ribbon(code, size) -- Start by getting the ribbon. Call the function designed to do that    end    local output = output ..  " [[" .. data[code].PageLink .. "|" .. data[code].Description .. "]] "  -- add the  pagelink and description    if data[code].Class then    if string.len(data[code].Class) > 0 then -- Only add the Class if there is something in the field     output = output .. " (''" .. data[code].Class .. "'') "     end    end    if string.len(data[code].PostNom) > 0 then -- Only add the postnom if there is something in the field      output = output .. " ('''" .. data[code].PostNom .. "''') "     end    if string.len(data[code].Note) > 0 then -- Only add the Note if there is something in the field     output = output .. mw.getCurrentFrame():expandTemplate{ title = 'Efn', args = {data[code].Note} } -- Note: Page needs {{notelist}}-- output = output .. "<sup>" .. data[code].Note .. "</sup> "     end    if string.len(country) > 0 then -- if a value for country has been specificed        if country:upper() ~= data[code].Country:upper() then -- check that the country specificed does NOT equal that on record            output = output .. " (" .. data[code].Country .. ") " -- add the country code to the end of the output        end    end    if string.len(org) > 0 then -- if a value for org has been specificed        if org:upper() == "YES" then -- check that it is YES            if string.len(data[code].Org) > 0 then -- Check there is actually something in the org field                output = output .. " (''" .. data[code].Org .. "'') " -- add the Org code to the end of the output            end        end    end    -- Optimised code. string.len is expensive as is local nocat_length = string.len(nocat)if nocat_length > 1 then -- If ANYTHING has been specified as a value for nocat, then it's true    -- Do nothing or add to tracking category?else    -- Need to exclude adding the recipient category if it is not in mainspace.    -- for now, that means checking it's not in "Template:" or "User:" space    local current_title = mw.title.getCurrentTitle()    local namespace = current_title.nsText    local namespace_length = string.len(namespace)    if namespace_length < 2 then        local recipcat = data[code].RecipCat or "" -- If there is a recipient category specified, then add it to the output        local categories = {}        --categories[#categories+1] = " [[Category:MilAward Ribbon Description]]" -- Add tracking Category -- Note commented out        if string.len(recipcat) > 0 then            local categoryTitle = mw.title.new('Category:' .. mw.text.trim(recipcat))            if categoryTitle.exists and not categoryTitle.isRedirect then                -- category exists and is not a redirect                categories[#categories+1] = " [[Category:" .. recipcat .. "]]"            else                -- category does not exist or is a redirect                -- Add to a tracking Category ???            end        end        output = output .. table.concat(categories)    endend    return outputendfunction p.RibbonDesc(frame)local templateArgs = getArgs(frame)-- local templateArgs = frame.args    local code = 'Unknown' -- initialise a local variable called code to something rational    local size = 'x20px' -- initialise a local variable called size to something rationalif templateArgs[1] then code = templateArgs[1] end -- check that it is not "nil" before assigning the value     if templateArgs[2] then size = templateArgs[2] end -- Check that it is not "nil" before assigning the valuelocal namedcode = templateArgs["code"] -- assign tha local variable "namedcode" to the value of the argument called codeif namedcode then  -- if the assignment of value has worked ie there was actially a parameter called code with a value then code = namedcode -- assign the value found above to the variable "code" overwriting any other value it may have hadendlocal namedsize = templateArgs["size"] -- exactly the same as for "code" aboveif namedsize thensize = namedsizeend    local namedcountry = templateArgs["country"] or '' -- if the argument "country" has been passed, assign it to a local variable    local country = namedcountry    local norib = templateArgs["norib"] or ''if not size then size = "x20px" end -- this is a weasel statement meant to assign the default value if the                                         -- variable doesn't hold one which should never occur if not code or '' == code then -- if thre was no code assigned (field empty) then return an error of invalud code-- '<span style="color:#d33">Error: missing positional parameter 1</span>'local output =  '<span style="color:#d33"> (Invalid Code: <b>' .. code .. '</b>)</span>'        return outputendif string.match(code, "%*") then -- The code field has asterisks in it. Raise an error local output = '<span style="color:#d33"> Bad Code: <b>[' .. code .. ']</b>. Replace all * with x</span> [[Category:MilAward Error]]'return outputend -- End if--local code = templateArgs[1]:upper() -- Do not convert to uppercase. Codes are case sensitiveif not data[code] then--return '<span style="color:#d33">Error: invalid positional parameter 1: ' .. code .. '</span>'return '<span style="color:#d33"> (Code: <b>' .. code .. '</b> Not found)</span>'end    local nocat= templateArgs["nocat"] or '' -- Assign local value for nocat parameter    local org=templateArgs["org"] or '' -- Assign local value for org parameterreturn _RibbonDesc (code, size, country, norib, nocat, org)endfunction p.Stack(frame)    GlobalTemplateArgs = getArgs(frame)    -- local size = GlobalTemplateArgs[1] or "x12px"    local size = "x12px"    local namedsize = GlobalTemplateArgs["size"]    if namedsize then        size = namedsize    else        size = "x12px"    end    local output = ''    local RibbonList = {}    for i = 1, 40 do -- 40 is the max number of params that will be examined.         local rl = GlobalTemplateArgs[i] or ""        if rl ~= "" then            table.insert(RibbonList, rl)        end    end    local row={}    for i, rl in ipairs(RibbonList) do        if rl ~= "" then            if data[rl] then -- check whether this is found in the data    local rowoutput = _Ribbon(rl, size)     table.insert(row,string.format('%s',rowoutput) )            end        end    end    output = table.concat(row, " ")    --output = output .. "[[Category:MilAward Stack]]" -- Add tracking category    return outputendfunction p.DescList(frame)    local templateArgs = getArgs(frame)    local size = templateArgs["size"] or 'x20px'    local namedcountry = templateArgs["country"] or 'yes'    local output = '\n'    for key, value in pairs(templateArgs) do        if string.len(value) > 1 and data[value] then                output = output .. "* " .. _RibbonDesc(value, size, namedcountry,'','','') .. "\n"        end    end    return outputendfunction p.PostNom(frame)    local templateArgs = getArgs(frame)    local size = templateArgs["size"] or '85%'    local sep = templateArgs["sep"] or ', '    if sep == "none" then        sep = " "    end    local output = '<span class="noexcerpt nowraplinks" style="font-size:' .. size .. '; font-weight:normal;">'    for key, value in pairs(templateArgs) do        if key ~= "size" and string.len(value) > 1 and data[value] then            if string.len(data[value].PostNom) > 1 then                output = output .. "[[" .. data[value].PageLink .. "|" ..  data[value].PostNom .. "]]" .. sep .. ""            end        end    end    local seplen = (string.len(sep) + 1) * -1 -- Take length of sep, add one to it and make it negative (* -1)    output = output:sub(1, seplen) -- Remove the trailing seperator    output = output .. '</span>'    return outputend-- Initial code by John Dovey (13 April 2023) [[User:BoonDock]]return p