Module:Build bracket/StateChecks
Appearance
local StateChecks = {}
-- Local mini-helpers (kept internal so we don't depend on Helpers here)
local function isempty(s) return s == nil or s == '' end
local function notempty(s) return s ~= nil and s ~= '' end
-- isBlankEntry: true if no team/text present for a cell
function StateChecks.isBlankEntry(state, j, i)
local colEntries = state.entries[j]
if not colEntries then return true end
local e = colEntries[i]
if not e then return true end
return isempty(e.team) and isempty(e.text)
end
-- showSeeds: decide whether to display the seed cell for a team row
function StateChecks.showSeeds(state, config, j, i)
local row = state.entries[j]
if not row then return false end
local e = row[i]
if not e or e.ctype ~= 'team' then return false end
if config.forceseeds or notempty(e.seed) then
return true
end
local group = e.group
local tpm = state.teamsPerMatch[j] or 2
local step = 2
local function neighborHasSeed(idx)
local n = row[idx]
return n and n.ctype == 'team' and n.group == group and notempty(n.seed)
end
for k = 1, tpm - 1 do
local plus = i + step * k
local minus = i - step * k
if plus <= config.r and neighborHasSeed(plus) then return true end
if minus >= 1 and neighborHasSeed(minus) then return true end
end
return false
end
-- teamLegs: effective #legs for a team row, honoring per-entry overrides and autolegs
function StateChecks.teamLegs(state, config, j, i)
local col = state.entries[j]
if not col then return state.rlegs[j] or 1 end
local e = col[i]
if not e or e.ctype ~= 'team' then
return state.rlegs[j] or 1
end
local legs = state.rlegs[j] or 1
if notempty(e.legs) then
legs = tonumber(e.legs) or legs
end
-- treat nil/'' and values containing 'nbsp' as blank
local function isScoreBlank(v)
if isempty(v) then return true end
return type(v) == 'string' and v:find('nbsp', 1, true) ~= nil
end
-- autolegs: count contiguous non-blank leg entries starting at 1
if config.autolegs and e.score then
local l = 1
while not isScoreBlank(e.score[l]) do
l = l + 1
end
local inferred = l - 1
if inferred > 0 then
legs = inferred
end
end
return legs
end
-- roundIsEmpty: scan forward until next header; true if only blanks in that round
function StateChecks.roundIsEmpty(state, config, j, i)
local col = state.entries[j]
if not col then return true end
local row = i + 1
while row <= config.r do
local e = col[row]
if e and e.ctype == 'header' then
break
end
if not StateChecks.isBlankEntry(state, j, row) then
return false
end
row = row + 1
end
return true
end
-- defaultHeaderText: mirror the built-in naming ("Final", "Semifinals", etc.)
function StateChecks.defaultHeaderText(config, j, headerindex)
if headerindex ~= 1 then
return 'Lower round ' .. tostring(j)
end
local c = tonumber(config.c) or j
local rem = c - j
if rem == 0 then
return 'Final'
elseif rem == 1 then
return 'Semifinals'
elseif rem == 2 then
return 'Quarterfinals'
else
return 'Round ' .. tostring(j)
end
end
-- noPaths: true if there are no path segments adjacent to the entry at (j,i)
function StateChecks.noPaths(state, j, i)
local cols = state.hascross[j] and 3 or 2
local pcj = state.pathCell[j]
local pci = pcj and pcj[i]
if pci then
for k = 1, cols do
local ktab = pci[k]
local dir1 = ktab and ktab[1]
if dir1 then
for n = 1, 4 do
local v = dir1[n]
if v and v ~= 0 then
return false
end
end
end
end
end
if state.hascross[j] then
local ccj = state.crossCell[j]
local cci = ccj and ccj[i]
if cci then
local left = cci.left
local right = cci.right
if (left and left[1] == 1) or (right and right[1] == 1) then
return false
end
end
end
return true
end
return StateChecks