Edge Rewrite
// request.cf · coarse context

A page that knows where it met you.

Only coarse request metadata is shown. This demo does not display or persist visitor IP addresses.

Country
US
Cloudflare location
CMH
Connection
HTTP/2
Language
Not provided

Ray ID: a44e97156c9c4af4

Jump to content

Module:Legislature/US

From Wikipedia, the free encyclopedia
-- local base = require('Module:Legislature')
local base
-- -- Blindly map local package layout into scope
-- local members = mw.loadData('Module:Legislature/US/lower/members')
-- local seats = mw.loadData('Module:Legislature/US/lower/seats')

-- -- Alias the base functions so formatters can see them
-- local qidToWikilink = base.qidToWikilink
-- local getArgs = base.getArgs
local lang = mw.language.getContentLanguage()


local p = {}

p.name = "Congress"
p.current_congress = 119
p.current_session = 2

-- other stuff probably - if there are any truly joint commissions (as opposed to commissions where the House and Senate appoint the members separately), i guess they might go here. not sure about functions.


-- ============================================================================
-- ROSTER BY STATE
-- Returns: Unsorted dictionary of district data for the given state code
-- ============================================================================
function p.stateToRoster(seats, state)
    -- if not state or not seats[state] then return nil end
    return seats[state]
end


-- make this compatible with the universal functions in Module:Legislature
function p.flattenDistricts(seats)
	local dict = {}
	for state_abbr, state_districts in pairs(seats) do
		for district_number, data in pairs(state_districts) do
			dict[state_abbr .. "-" .. tostring(district_number)] = data
		end
	end
	return dict
end

p.getSeats = p.flattenDistricts -- standard name


-- ============================================================================
-- FORMATTING HELPERS
-- ============================================================================
-- Helper: Format a single member line (e.g., "* [[Jim Jordan]], Ohio, ''Chair''")
local function formatMemberLine(member_info, is_majority, committee_bloc_party)
    -- local rep = members[member_info.rep_id]
    -- if not rep then return "" end

	if member_info.former then
		local line = "* " .. member_info.rep_wikilink_and_state
		
	    local mdy = lang:formatDate("F j, Y", member_info.end_date)
		line = line .. " (until " .. mdy .. ")"

		if member_info.note ~= nil then
			line = line .. member_info.note
		end
		
		local party = member_info.party
		if party ~= committee_bloc_party then
			line = "<span {{Party shading/" .. party .. "}}>" .. line .. "</span>"
		end
		
		return line
	end
    
    -- Extract the 2-letter state abbreviation from their seat ID (e.g., "TX" from "TX-15")
    local seat_id = base.repIDToSeatID(member_info.rep_id)
    -- local state_abbr = "Unknown"
	local state_abbr = string.sub(seat_id, 1, 2) -- TODO: this is terrible and should be a function. LLMs should be banned from using string operations
    -- local state_name = stateMap[state_abbr] or state_abbr
	
    local line = base.qidToWikilink(member_info.rep_id) .. ", " .. "{{US state abbreviation to name|" .. state_abbr .. "}}"

	local rep_data = base.getMember(member_info.rep_id)
	local party = rep_data.party
	if party ~= committee_bloc_party then
		line = "<span {{Party shading/" .. party .. "}}>" .. line
	end
	line = "* " .. line
    
    -- Append MVP leadership titles based on rank == 1 - "chair", "vice chair", etc., are in the xml file directly
    if member_info.rank == 1 and not is_majority then
		line = line .. ", ''Ranking Member''"
	elseif member_info.leadership ~= nil then
		line = line .. ", ''" .. member_info.leadership .. "''"
	end

	if member_info.start_date ~= nil then
	    -- Format the date into "Month DD, YYYY"
	    local mdy = lang:formatDate("F j, Y", member_info.start_date)
		line = line .. " (from " .. mdy .. ")"
	end

	-- Append any custom note
    if rep_data.note_committees ~= nil then
        line = line .. rep_data.note_committees
    end

	if member_info.note ~= nil then
		line = line .. member_info.note
	end
	
	if rep_data.party ~= committee_bloc_party then
		line = line .. "</span>"
	end
    
    return line
end

-- ============================================================================
-- WIKITEXT FORMATTERS (Callable by Templates)
-- ============================================================================
function p.formatCommitteeRosterTable(frame, base_module)
	base = base_module
    local args = base.getArgs(frame)
    -- -- Tell the base module to load the data paths passed from the template
    -- base.initEnvironment(args)
	
    local committee_name = args.committee or args[1]
    -- if not committee_name then return "Error: No committee specified." end
    
    -- 1. Call your existing, unmodified data function
    local committee_id = base.committeeNameToID(committee_name)
    local raw_roster = base.committeeIDToRoster(committee_id)
    -- if not raw_roster then return "Error: Committee not found." end

	-- local roster_copy = {}
	-- for _, member_info in ipairs(raw_roster) do
 --        -- Shallow copy the read-only mw.loadData table so it can be mutated
	-- 	local m_copy = {}
 --        for k, v in pairs(member_info) do m_copy[k] = v end
        
 --        -- if m_copy.party_status == "majority" then
 --        --     table.insert(majority_list, m_copy)
 --        -- else
 --        --     assert(m_copy.party_status == "minority")
 --        --     table.insert(minority_list, m_copy)
 --        -- end

	-- 	table.insert(roster_copy, m_copy)
 --    end

	-- raw_roster = roster_copy
    
    -- 2. Sort the roster array into majority and minority groups
    local majority_list = {}
    local minority_list = {}
    
    for _, member_info in ipairs(raw_roster) do
		local m_copy = {}
        for k, v in pairs(member_info) do m_copy[k] = v end

        if m_copy.party_status == "majority" then
            table.insert(majority_list, m_copy)
        -- if member_info.party_status == "majority" then
        --     table.insert(majority_list, member_info)
        -- elseif member_info.party_status == "minority" then
		else
			assert(m_copy.party_status == "minority")
            table.insert(minority_list, m_copy)
			-- assert(member_info.party_status == "minority")
            -- table.insert(minority_list, member_info)
        end
    end

	-- Parse and inject ad hoc former members
    if args.former_members then
        -- Split the string by semicolon to get individual members
        local former_arr = mw.text.split(args.former_members, "%s*;%s*")
        
        for _, fm_str in ipairs(former_arr) do
            -- if fm_str ~= "" then
			-- Split by caret to get the fields
			local parts = mw.text.split(fm_str, "%s*^%s*")
			local rep_wikilink_and_state = parts[1]
			local end_date = parts[2]
		    -- local mdy = lang:formatDate("F j, Y", end_date)
			local party_status = parts[3]
			local party = parts[4] or nil
			local rank = tonumber(parts[5]) or 9999 -- Assign an artificially high rank to force them to the bottom -- TODO: not the standard that is done but rather something the LLM decided was right
			
			-- Build a record
			local member = {
				former = true,
				rep_wikilink_and_state = rep_wikilink_and_state,
				party_status = party_status,
				rank = rank,
				party = party,
				end_date = end_date
				-- note = "(until " .. mdy .. ")"
			}
			
			if party_status == "majority" then
				table.insert(majority_list, member)
			elseif party_status == "minority" then
				table.insert(minority_list, member)
			end
            -- end
        end
    end
    
    -- Sort both lists by their rank integer -- TODO: probably unnecessary since it should already be in order
    table.sort(majority_list, function(a, b) return (a.rank or 999) < (b.rank or 999) end) -- note: i actually don't mind the LLM's defaults here too much
    table.sort(minority_list, function(a, b) return (a.rank or 999) < (b.rank or 999) end)
    
    -- 3. Dynamically determine column party colors based on the Chair and Ranking Member -- TODO: this could be done by just having a field populated in Legislature/US/lower and Legislature/US/upper that tells us who the majority party is - this data is available in the house clerk's xml document - but technically this is more robust because of the possibility of split control and power-sharing and such
	local maj_party = majority_list[1] and base.getMember(majority_list[1].rep_id).party
	local min_party = minority_list[1] and base.getMember(minority_list[1].rep_id).party
    
    -- -- Sort both lists by their rank integer
    -- table.sort(majority_list, function(a, b) return (a.rank or 9999) < (b.rank or 9999) end) -- i don't hate the LLM's defaults here
    -- table.sort(minority_list, function(a, b) return (a.rank or 9999) < (b.rank or 9999) end)

	-- 3.5 Process Ex Officio members if this is a subcommittee

    local parent_id = base.subcommitteeIDToParentCommitteeID(committee_id)
	local ex_maj_line, ex_min_line
	
    if parent_id ~= nil then
        local parent_roster = base.committeeIDToRoster(parent_id)
        local p_maj_chair, p_min_chair

        -- if parent_roster then
		for _, m in ipairs(parent_roster) do
			if m.rank == 1 then
				if m.party_status == "majority" then
					p_maj_chair = m
				elseif m.party_status == "minority" then
					p_min_chair = m
				end
			end
		end
        -- end
		
		local function handleExOfficio(parent_top_ranked_member, subcommittee_list, is_majority, column_party)
            -- if not parent_top_ranked_member then return "" end

            local rep_id = parent_top_ranked_member.rep_id
            
            -- -- Extract the last name from the wikilink target/label -- TODO
            -- local label = mw.wikibase.label(rep_id) or mw.wikibase.sitelink(rep_id) or ""
            -- local last_name = label:match("(%S+)%s*$") or label

			local rep_name = base.getMember(rep_id).rep_name
            local title = is_majority and "Chair" or "Ranking Member"

            -- local formulaic_note = "<ref >As " .. title .. " of the full committee, Rep. " .. rep_name .. " is entitled to sit as an ''ex officio'' member of all subcommittees, but has been designated a full member of this subcommittee.</ref>"
			local ref_name = "exofficio_" .. rep_id
            local full_ref = '<ref name="' .. ref_name .. '">As ' .. title .. ' of the full committee, Rep. ' .. rep_name .. ' is entitled to sit as an \'\'ex officio\'\' member of all subcommittees, but has been designated a full member of this subcommittee.</ref>'
            local short_ref = '<ref name="' .. ref_name .. '" />'

            -- Check if they are already on the subcommittee
            for _, m in ipairs(subcommittee_list) do
                if m.rep_id == rep_id then
                    -- m.note = (m.note or "") .. formulaic_note
                    -- return "* " .. formulaic_note
					m.note = (m.note or "") .. full_ref
                    return "* " .. short_ref
                end
            end

            -- Build a mock member for the standalone Ex Officio line. 
            -- Overriding rank to 999 prevents formatMemberLine from adding subcommittee MVP titles. -- idk what the llm meant by "MVP". maybe like "vice chair" or "chair".
            return formatMemberLine({rep_id = rep_id, rank = 999}, is_majority, column_party)
        end

        ex_maj_line = handleExOfficio(p_maj_chair, majority_list, true, maj_party)
        ex_min_line = handleExOfficio(p_min_chair, minority_list, false, min_party)
    end
    
    -- 4. Format the strings for each member
    local maj_lines = {}
    for _, m in ipairs(majority_list) do
        table.insert(maj_lines, formatMemberLine(m, true, maj_party))
    end
    
    local min_lines = {}
    for _, m in ipairs(minority_list) do
        table.insert(min_lines, formatMemberLine(m, false, min_party))
    end
    
    -- 5. Construct the final Wikitable string
    local out = {}
    table.insert(out, '{| class="wikitable"')
	-- table.insert(out, '|+ Committee roster{{User:Blippy1998/sandbox/HouseClerkXMLCitation}}')
    -- table.insert(out, '! Majority\n! Minority')
    table.insert(out, '! Majority{{User:Blippy1998/sandbox/HouseClerkXMLCitation|name=house_clerk_member_data_xml}}\n! Minority<ref name=house_clerk_member_data_xml/>')
    table.insert(out, '|-')
    
    -- Majority Column
    table.insert(out, '| valign="top" {{Party shading/' .. maj_party .. '}} |')
    table.insert(out, table.concat(maj_lines, "\n"))
    
    -- Minority Column
    table.insert(out, '| valign="top" {{Party shading/' .. min_party .. '}} |')
    table.insert(out, table.concat(min_lines, "\n"))
	
	-- 6. Append Ex Officio Rows (if it's a subcommittee)
    if parent_id ~= nil then
        table.insert(out, '|-')
        table.insert(out, '! colspan="2" | \'\'Ex officio\'\'')
        table.insert(out, '|-')
        
        table.insert(out, '| valign="top" {{Party shading/' .. maj_party .. '}} |')
        table.insert(out, ex_maj_line)
        
        table.insert(out, '| valign="top" {{Party shading/' .. min_party .. '}} |')
        table.insert(out, ex_min_line)
    end
    
    table.insert(out, '|}')
    
    local final_wikitext = table.concat(out, "\n")
	if type(frame) == 'table' and type(frame.preprocess) == 'function' then
        return frame:preprocess(final_wikitext)
    end
    return final_wikitext
end


function p.committeeMeetingPlace(committee)
	local building_codes = {
	    ["CHOB"] = "Cannon House Office Building",    -- https://clerk.house.gov/member_info/MemberData_UserGuide.pdf
	    ["LHOB"] = "Longworth House Office Building", -- https://clerk.house.gov/member_info/MemberData_UserGuide.pdf
	    ["RHOB"] = "Rayburn House Office Building",   -- https://clerk.house.gov/member_info/MemberData_UserGuide.pdf
	    ["FHOB"] = "Ford House Office Building",      -- https://clerk.house.gov/member_info/MemberData_UserGuide.pdf
	    ["OFOB"] = "O'Neill House Office Building",   -- https://clerk.house.gov/member_info/MemberData_UserGuide.pdf
	    ["H"] = "The Capitol",                        -- https://www.govinfo.gov/content/pkg/CDIR-2016-02-12/pdf/CDIR-2016-02-12-HOUSECOMMITTEES.pdf
	    ["C"] = "The Capitol",                        -- https://www.govinfo.gov/content/pkg/CDIR-2016-02-12/pdf/CDIR-2016-02-12-HOUSECOMMITTEES.pdf
	    ["HB"] = "The Capitol",                       -- https://clerk.house.gov/member_info/TTD-119.pdf
	    ["HT"] = "The Capitol",                       -- https://clerk.house.gov/member_info/TTD-119.pdf
	    ["HVC"] = "Capitol Visitor Center",           -- https://clerk.house.gov/member_info/TTD-119.pdf
	    ["CVC"] = "Capitol Visitor Center",           -- https://clerk.house.gov/member_info/TTD-119.pdf
	    ["DSOB"] = "Dirksen Senate Office Building",  -- https://www.senate.gov/visiting/common/generic/building_abbreviation_key.htm
	    ["RSOB"] = "Russell Senate Office Building",  -- https://www.senate.gov/visiting/common/generic/building_abbreviation_key.htm
	    ["HSOB"] = "Hart Senate Office Building"      -- https://www.senate.gov/visiting/common/generic/building_abbreviation_key.htm
	}
	return committee.room .. ", " .. building_codes[committee.building_code] .. "<br/>" .. "Washington, D.C. " .. committee.zip
end


return p