Module:USASpending-by-category
From Defense Knowledge
Documentation for this module may be created at Module:USASpending-by-category/doc
local autoCreate = require('Module:AutoCreateWithPreload')
local p = {}
-- Get current language
local lang = mw.language.getContentLanguage()
-- Function to format number with two decimals and group separator
function formatNumberWithSeparator(num)
local integerPart = math.floor(num)
local decimalPart = string.format("%.2f", num - integerPart):sub(3)
-- Format the integer part with group separators
local formattedInteger = lang:formatNum(integerPart)
-- Combine integer part and decimal part
return formattedInteger .. "." .. decimalPart
end
function p.retrieveData(frame)
-- Handle arguments
local limit = frame.args.limit or 5
local heading = frame.args.heading or ""
local urlPath = frame.args.urlPath or ""
local headingClass = frame.args.headingClass or "mt-5"
-- Preload template for autocreated pages
local acpTemplate = frame.args.acpTemplate or ""
-- Get pagename
local pageName = frame.args.page or mw.title.getCurrentTitle().text
-- Set the API URL
local baseUrl = 'https://api.usaspending.gov'
local queryUrl = '/api/v2/search/spending_by_category/' .. urlPath
local apiUrl = baseUrl .. queryUrl
-- Handling the latest year period
local dateTable = os.date("*t")
local currentYear = dateTable.year
local lastYear = currentYear - 1
local yearAgo = {
year = lastYear,
month = dateTable.month,
day = dateTable.day
}
local timestamp = os.time(yearAgo)
local dateFrom = os.date("%Y-%m-%d", timestamp)
local dateTo = os.date("%Y-%m-%d")
-- Define POST data
local postData = '{"filters":{"recipient_id":"' .. pageName .. '","time_period":[{"start_date":"' .. dateFrom .. '","end_date":"' .. dateTo .. '"}]},"limit":' .. limit .. '}'
-- Fetch data from the API
local data = mw.ext.externalData.getWebData {
url = apiUrl,
format = 'JSON',
['post data'] = postData,
data = {code = 'code', name = 'name', amount = 'amount'},
['cache seconds'] = 86400
}
-- Assemble HTML output
local output = {}
-- Calculate total amount
local totalAmount = 0
local recordCount = 0
if #data > 0 then
for _, record in ipairs(data) do
local amount = record.amount or 0
totalAmount = totalAmount + amount
recordCount = recordCount + 1
end
end
if recordCount > 0 then
-- Start building the table
if heading ~= "" then
table.insert(output, '<div class="h4 text-secondary border-bottom border-dark pb-2 ' .. headingClass .. '">' .. heading .. '</div>')
end
table.insert(output, '<table class="w-100 mt-0 wikitable sortable">')
-- Add table headers
table.insert(output, '<tr>')
table.insert(output, '<th width="110">Code</th>')
table.insert(output, '<th>Name</th>')
table.insert(output, '<th width="190">Obligations</th>')
table.insert(output, '<th width="190">% of Total</th>')
table.insert(output, '</tr>')
-- Add table rows
for _, record in ipairs(data) do
local percentage = (record.amount / totalAmount) * 100 or 0
local code = record.code or "N/A"
local name = record.name or "N/A"
table.insert(output, '<tr>')
table.insert(output, '<td>' .. code .. '</td>')
if acpTemplate ~= "" then
table.insert(output, '<td class="cell-overflow-hidden" title="' .. name .. '">[[' .. name .. ']]</td>')
else
table.insert(output, '<td class="cell-overflow-hidden" title="' .. name .. '">' .. name .. '</td>')
end
table.insert(output, '<td align="right" data-sort="' .. record.amount .. '">' .. formatNumberWithSeparator(record.amount) .. '</td>')
if tostring(percentage) == "nan" then
table.insert(output, '<td align="right" data-sort="--">--</td>')
else
table.insert(output, '<td align="right" data-sort="' .. string.format("%.2f", percentage) .. '">' .. string.format("%.2f%%", percentage) .. '</td>')
end
table.insert(output, '</tr>')
-- Autocreate non-existing pages from links
if acpTemplate ~= "" then
table.insert(output, autoCreate.autoCreateWithPreload(frame, record.name, '{{' .. acpTemplate .. '}}'))
end
end
-- Close the table
table.insert(output, '</table>')
end
local result = table.concat(output, "\n")
return result
end
return p