Module:Sandbox/Blippy1998

local p = {}

-- Helper to mimic PHP's explode(delimiter, string, 2)
local function split_once(str, delimiter)
    local pos = mw.ustring.find(str, delimiter, 1, true)
    if pos then
        return mw.ustring.sub(str, 1, pos - 1), mw.ustring.sub(str, pos + mw.ustring.len(delimiter))
    end
    return str, nil
end

function p.parseTablesToData(text)
    local lines = mw.text.split(text, "\n")
    
    local parsed_data = {}
    local current_table = nil
    local current_row = nil
    
    for _, outLine in ipairs(lines) do
        local line = mw.text.trim(outLine)
        
        -- Equivalent to skipping via 'continue'
        if line ~= '' then
            local first_char = mw.ustring.sub(line, 1, 1)
            local first_two = mw.ustring.sub(line, 1, 2)
            
            local indent_match, attributes_match = mw.ustring.match(line, "^(:*)%s*%{%|(.*)$")
            
            if indent_match then
                -- Start a new table
                current_table = {
                    attributes = mw.text.unstrip(attributes_match),
                    rows = {}
                }
                table.insert(parsed_data, current_table)
                current_row = nil
                
            elseif not current_table then
                -- Not inside a table, do nothing (skip)
                
            elseif first_two == '|}' then
                -- End the current table
                current_table = nil
                current_row = nil
                
            elseif first_two == '|-' then
                -- Start a new row
                line = mw.ustring.gsub(line, "^|%-+", "")
                current_row = {
                    attributes = mw.text.unstrip(line),
                    cells = {}
                }
                table.insert(current_table.rows, current_row)
                
            elseif first_char == '|' or first_char == '!' or first_two == '|+' then
                -- Process cells, headers, or captions
                
                -- Handle implicit rows (if cell data appears before a |- tag)
                if not current_row and first_two ~= '|+' then
                    current_row = { attributes = "", cells = {} }
                    table.insert(current_table.rows, current_row)
                end
                
                if first_two == '|+' then
                    first_char = '+'
                    line = mw.ustring.sub(line, 3)
                    current_table.caption = mw.text.trim(mw.text.unstrip(line))
                else
                    line = mw.ustring.sub(line, 2)
                    
                    if first_char == '!' then
                        line = mw.ustring.gsub(line, "!!", "||")
                    end
                    
                    local cells = mw.text.split(line, "||", true)
                    
                    for _, cell_str in ipairs(cells) do
                        local cell_type = (first_char == '!') and "th" or "td"
                        local cell_attr_str, cell_content_str = split_once(cell_str, "|")
                        
                        local cell_obj = {
                            type = cell_type,
                            attributes = "",
                            content = ""
                        }
                        
                        -- Replicate PHP's logic to check for [[ links or -{ language converter tags
                        -- to ensure a pipe inside a link isn't mistaken for an attribute delimiter.
                        if not cell_content_str or mw.ustring.match(cell_attr_str, "%[%[") or mw.ustring.match(cell_attr_str, "%-%{") then
                            cell_obj.content = mw.text.trim(cell_str)
                        else
                            cell_obj.attributes = mw.text.unstrip(cell_attr_str)
                            cell_obj.content = mw.text.trim(cell_content_str)
                        end
                        
                        table.insert(current_row.cells, cell_obj)
                    end
                end
            end
        end
    end
    
    return parsed_data
end

function p.testLoadPage(frame)
    -- 1. Define the page title to load. 
    -- Note: Testing this on the full US Reps page immediately will yield a massive dump string.
    -- I recommend creating a subpage with a small test table first.
    local page_title = "List of current United States representatives#List of representatives" 
    
    local titleObj = mw.title.new(page_title)
    if not titleObj then return "Error: Invalid title." end

    -- 2. Fetch the raw wikitext
    local content = titleObj:getContent()
    if not content then return "Error: Page not found or empty." end

    -- 3. Run the parser
    local parsed_data = p.parseTablesToData(content)[6]

    -- 4. Dump the resulting Lua table as a preformatted string so you can read the structure
    return "<pre>\n" .. mw.dumpObject(parsed_data) .. "\n</pre>"
end

function p.tallyParties(frame)
    -- 1. Load the page and parse the text
    local page_title = "List of current United States representatives#List of representatives" 
    local titleObj = mw.title.new(page_title)
    if not titleObj then return "Error: Invalid title." end

    local content = titleObj:getContent()
    if not content then return "Error: Page not found or empty." end

    local parsed_data = p.parseTablesToData(content)[6]
    if not parsed_data then return "Error: Table not found." end

    -- 2. Build a dynamic column map from the header row
    local column_map = {}
    local current_col = 1
    local header_row = parsed_data.rows[1]
    
    for _, cell in ipairs(header_row.cells) do
        -- Clean the header text (removes <ref> tags and hidden spans)
        local header_text = mw.ustring.gsub(cell.content, "<[^>]+>", "")
        header_text = mw.text.trim(header_text)
        
        -- Check if this header spans multiple columns (e.g., colspan=2)
        local colspan = 1
        local colspan_match = mw.ustring.match(cell.attributes, "colspan%s*=%s*[\"']?(%d+)[\"']?")
        if colspan_match then
            colspan = tonumber(colspan_match)
        end
        
        column_map[header_text] = {
            start_index = current_col,
            span = colspan,
            -- For Party, the text name is in the right-most cell of the span
            end_index = current_col + colspan - 1 
        }
        
        current_col = current_col + colspan
    end

    -- Abort if we can't find the Party column
    if not column_map["Party"] then return "Error: Could not find 'Party' column." end
    
    -- Extract the exact index we need to check in the data rows
    local party_col_index = column_map["Party"].end_index

    -- 3. Initialize the tally counters
    local tallies = {
        Democratic = 0,
        Republican = 0,
        Independent = 0,
        Vacant = 0
    }

    -- 4. Iterate through the data rows
    for i = 2, #parsed_data.rows do
        local row = parsed_data.rows[i]
        local cells = row.cells
        
        if #cells > 0 then
            
            -- Check for vacant seats (vacant rows use a massive colspan, yielding fewer cells)
            if #cells < party_col_index then
                assert(#cells == 2, "Row had " .. #cells .. " cells. Expected 2.")
                assert(cells[2].content == "''Vacant''", "Expected ''Vacant'', got: " .. tostring(cells[2].content))
                tallies.Vacant = tallies.Vacant + 1
            else
                -- 5. Extract the party using the dynamic index
                local party = cells[party_col_index].content
                
                party = mw.ustring.gsub(party, "<[^>]+>", "")
                party = mw.text.trim(party)
                
                if tallies[party] ~= nil then
                    tallies[party] = tallies[party] + 1
                else
                    tallies[party] = 1
                end
            end
            
        end
    end

    -- 6. Format the output
    local output = "'''Current House Tallies:'''\n"
    output = output .. "* Democratic: " .. tallies.Democratic .. "\n"
    output = output .. "* Republican: " .. tallies.Republican .. "\n"
    output = output .. "* Independent: " .. tallies.Independent .. "\n"
    output = output .. "* Vacant: " .. tallies.Vacant .. "\n"
    
    return output
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.