Module:WarLeagueUnitUtilizationBVR
From MicrasWiki
Documentation for this module may be created at Module:WarLeagueUnitUtilizationBVR/doc
local unitName = extractDisplayText(parts[2])
-- 1) Build per-division column groups (handles shared divs like HFA across multiple columns)
local divCols = {} -- divCols[DIV] = { {idx=i, avail=n}, ... }
local availByIdx = {} -- availByIdx[i] = n
for i = 4, 14 do
local colKey = COL_KEYS[i - 3]
local divCode = COL_TO_DIV[colKey]
local avail = toNumber(parts[i]) or 0
availByIdx[i] = avail
if divCode then
divCols[divCode] = divCols[divCode] or {}
table.insert(divCols[divCode], { idx = i, avail = avail })
end
end
-- 2) Allocate demand across columns (never exceeding availability)
local usedByIdx = {} -- usedByIdx[i] = allocated used
local shortByDiv = {} -- shortByDiv[DIV] = unmet demand (optional)
for divCode, cols in pairs(divCols) do
local demand = (util[divCode] and util[divCode][unitName]) or 0
if demand > 0 then
local totalAvail = 0
for _, c in ipairs(cols) do
totalAvail = totalAvail + (c.avail or 0)
end
local usedTotal = math.min(demand, totalAvail)
if demand > totalAvail then
shortByDiv[divCode] = demand - totalAvail
end
if totalAvail > 0 and usedTotal > 0 then
-- First pass: proportional floor allocation
local assigned = 0
for _, c in ipairs(cols) do
local share = math.floor(usedTotal * c.avail / totalAvail)
if share > c.avail then share = c.avail end
usedByIdx[c.idx] = share
assigned = assigned + share
end
-- Remainder distribution (adds 1s where there is capacity)
local rem = usedTotal - assigned
if rem > 0 then
-- Sort by remaining capacity descending
table.sort(cols, function(a, b)
local ca = (a.avail or 0) - (usedByIdx[a.idx] or 0)
local cb = (b.avail or 0) - (usedByIdx[b.idx] or 0)
return ca > cb
end)
local pass = 0
while rem > 0 do
pass = pass + 1
local progressed = false
for _, c in ipairs(cols) do
if rem <= 0 then break end
local cap = (c.avail or 0) - (usedByIdx[c.idx] or 0)
if cap > 0 then
usedByIdx[c.idx] = (usedByIdx[c.idx] or 0) + 1
rem = rem - 1
progressed = true
if rem <= 0 then break end
end
end
if not progressed or pass > 1000 then
-- Safety stop (shouldn't happen unless weird data)
break
end
end
end
end
end
end
-- 3) Apply styling to each cell using the allocated used counts (never exceeds avail)
for i = 4, 14 do
local avail = availByIdx[i] or 0
local used = usedByIdx[i] or 0
if avail > 0 and used > 0 then
local pct = used / avail
if pct > 1 then pct = 1 end -- hard safety
local bg = cellColor(pct)
local usedText = string.format(
"<br/><span style=\"font-size:85%%;\"><b>used:</b> %s</span>",
fmt(used)
)
parts[i] = string.format(
"style=\"background:%s; text-align:center;\" | %s%s",
bg,
parts[i],
usedText
)
end
end