Module:Timeline: Difference between revisions

From aquila
Jump to navigation Jump to search
mNo edit summary
mNo edit summary
Line 1: Line 1:
local p = {}
local p = {}


-- Constant base date for Year 1, Day 1
-- Base date for Year 1, Day 1: 2026-07-28
local BASE_TIMESTAMP = 1785206400 -- 2026-07-28 00:00:00 UTC
local BASE_TIMESTAMP = 1785206400 -- 2026-07-28 00:00:00 UTC
local SECONDS_PER_DAY = 86400
local SECONDS_PER_DAY = 86400
Line 13: Line 13:


local function calculateDate(year, dayIndex)
local function calculateDate(year, dayIndex)
    year = tonumber(year) or 1
    dayIndex = tonumber(dayIndex) or 1
     local daysOffset = (year - 1) * 14 + (dayIndex - 1)
     local daysOffset = (year - 1) * 14 + (dayIndex - 1)
     local targetTimestamp = BASE_TIMESTAMP + (daysOffset * SECONDS_PER_DAY)
     local targetTimestamp = BASE_TIMESTAMP + (daysOffset * SECONDS_PER_DAY)
     return os.date("Y-%m-%d", targetTimestamp)
     return os.date("!%Y-%m-%d", targetTimestamp)
end
end


local function formatLink(text, defaultNamespace)
local function formatLink(text)
     if not text or text == "" then return "" end
     if not text or text == "" then return "" end
     text = mw.text.trim(text)
     text = mw.text.trim(text)
     -- If already bracketed or contains HTML/quotes, leave it
     -- If already bracketed, quoted, or styled, don't wrap again
     if text:sub(1, 2) == "[[" or text:sub(1, 1) == "'" or text:sub(1, 1) == "<" then
     if text:sub(1, 2) == "[[" or text:sub(1, 1) == "'" or text:sub(1, 1) == "<" then
         return text
         return text
     end
     end
     return "[[" .."]"
     return "[[" .. text .. "]]"
end
end


Line 31: Line 33:
     local args = frame:getParent().args
     local args = frame:getParent().args
     local year = tonumber(args.Year) or 1
     local year = tonumber(args.Year) or 1
    local category = args.Category or "NEWS"
     local html = ""
     local html = ""


     -- We will parse 14 days. Collect events per day.
     -- Render Section Header Row
    html = html .. "|-\n"
    html = html .. '! colspan="4" style="background-color: #f1f5f9; color: #0b132b; text-align: center; font-weight: bold; padding: 6px;" | ' .. string.upper(category) .. ' NEWS\n'
 
    -- Collect events per day (up to 5 events per day)
     local schedule = {}
     local schedule = {}
     for i = 1, 14 do
     for i = 1, 14 do
         schedule[i] = {}
         schedule[i] = {}
         local pIdx = 1
         for pIdx = 1, 5 do
        while true do
             local post = args['Day' .. i .. '_' .. pIdx .. '_Post']
             local post = args['Day' .. i .. '_' .. pIdx .. '_Post']
             local char = args['Day' .. i .. '_' .. pIdx .. '_Char']
             local char = args['Day' .. i .. '_' .. pIdx .. '_Char']
             local dateOverride = args['Day' .. i .. '_' .. pIdx .. '_Date']
             local dateOverride = args['Day' .. i .. '_' .. pIdx .. '_Date']
              
              
             if not post or post == "" then break end
             if post and post ~= "" then
           
                 local formattedPost = formatLink(post)
            table.insert(schedule[i], {
                 local formattedChar = formatLink(char)
                 post = post,
                 local finalDate = (dateOverride and dateOverride ~= "") and dateOverride or calculateDate(year, i)
                 char = char or "",
               
                 date = dateOverride ~= "" and dateOverride or calculateDate(year, i)
                table.insert(schedule[i], {
            })
                    post = formattedPost,
             pIdx = pIdx + 1
                    char = formattedChar,
                    date = finalDate
                })
             end
         end
         end
     end
     end


     -- Loop through days to render, handling empty range collapsing
     -- Render Table Rows
     local i = 1
     local i = 1
     while i <= 14 do
     while i <= 14 do
Line 85: Line 94:
                 rangeLabel = dayNames[startEmpty] .. ", Year " .. year
                 rangeLabel = dayNames[startEmpty] .. ", Year " .. year
             else
             else
                rangeLabel = dayNames[startEmpty] .. " to " .. dayNames[endEmpty] .. ", Year " + year -- Note: handled cleanly below
                 rangeLabel = dayNames[startEmpty] .. " to " .. dayNames[endEmpty] .. ", Year " .. year
                 rangeLabel = dayNames[startEmpty] .. " to " .. dayNames[endEmpty] .. ", Year " .. year
             end
             end
Line 91: Line 99:
             local startDate = calculateDate(year, startEmpty)
             local startDate = calculateDate(year, startEmpty)
             local endDate = calculateDate(year, endEmpty)
             local endDate = calculateDate(year, endEmpty)
             local dateDisplay = (startEmpty == endEmpty) and startDate or (startDate + " to " + endDate)
             local dateDisplay = (startEmpty == endEmpty) and startDate or (startDate .. " to " .. endDate)
            dateDisplay = (startEmpty == endEmpty) and startDate or (startDate .. " to " .. endDate)
              
              
             html = html .. "|-\n"
             html = html .. "|-\n"

Revision as of 20:41, 23 October 2026

Documentation for this module may be created at Module:Timeline/doc

local p = {}

-- Base date for Year 1, Day 1: 2026-07-28
local BASE_TIMESTAMP = 1785206400 -- 2026-07-28 00:00:00 UTC
local SECONDS_PER_DAY = 86400

local dayNames = {
    "Early January", "January--February", "February--March", "March--April",
    "April--May", "May--June", "June", "June--July",
    "July--August", "August--September", "September--October",
    "October--November", "November--December", "Late December"
}

local function calculateDate(year, dayIndex)
    year = tonumber(year) or 1
    dayIndex = tonumber(dayIndex) or 1
    local daysOffset = (year - 1) * 14 + (dayIndex - 1)
    local targetTimestamp = BASE_TIMESTAMP + (daysOffset * SECONDS_PER_DAY)
    return os.date("!%Y-%m-%d", targetTimestamp)
end

local function formatLink(text)
    if not text or text == "" then return "" end
    text = mw.text.trim(text)
    -- If already bracketed, quoted, or styled, don't wrap again
    if text:sub(1, 2) == "[[" or text:sub(1, 1) == "'" or text:sub(1, 1) == "<" then
        return text
    end
    return "[[" .. text .. "]]"
end

function p.renderTable(frame)
    local args = frame:getParent().args
    local year = tonumber(args.Year) or 1
    local category = args.Category or "NEWS"
    local html = ""

    -- Render Section Header Row
    html = html .. "|-\n"
    html = html .. '! colspan="4" style="background-color: #f1f5f9; color: #0b132b; text-align: center; font-weight: bold; padding: 6px;" | ' .. string.upper(category) .. ' NEWS\n'

    -- Collect events per day (up to 5 events per day)
    local schedule = {}
    for i = 1, 14 do
        schedule[i] = {}
        for pIdx = 1, 5 do
            local post = args['Day' .. i .. '_' .. pIdx .. '_Post']
            local char = args['Day' .. i .. '_' .. pIdx .. '_Char']
            local dateOverride = args['Day' .. i .. '_' .. pIdx .. '_Date']
            
            if post and post ~= "" then
                local formattedPost = formatLink(post)
                local formattedChar = formatLink(char)
                local finalDate = (dateOverride and dateOverride ~= "") and dateOverride or calculateDate(year, i)
                
                table.insert(schedule[i], {
                    post = formattedPost,
                    char = formattedChar,
                    date = finalDate
                })
            end
        end
    end

    -- Render Table Rows
    local i = 1
    while i <= 14 do
        if #schedule[i] > 0 then
            local count = #schedule[i]
            local inUniverseLabel = dayNames[i] .. ", Year " .. year
            
            for idx, event in ipairs(schedule[i]) do
                html = html .. "|-\n"
                if idx == 1 then
                    html = html .. '| rowspan="' .. count .. '" | ' .. inUniverseLabel .. '\n'
                end
                html = html .. '| ' .. event.post .. '\n'
                html = html .. '| ' .. event.char .. '\n'
                if idx == 1 then
                    html = html .. '| rowspan="' .. count .. '" | ' .. event.date .. '\n'
                end
            end
            i = i + 1
        else
            -- Scan ahead for consecutive empty days to collapse ranges
            local startEmpty = i
            while i <= 14 and #schedule[i] == 0 do
                i = i + 1
            end
            local endEmpty = i - 1
            
            local rangeLabel = ""
            if startEmpty == endEmpty then
                rangeLabel = dayNames[startEmpty] .. ", Year " .. year
            else
                rangeLabel = dayNames[startEmpty] .. " to " .. dayNames[endEmpty] .. ", Year " .. year
            end
            
            local startDate = calculateDate(year, startEmpty)
            local endDate = calculateDate(year, endEmpty)
            local dateDisplay = (startEmpty == endEmpty) and startDate or (startDate .. " to " .. endDate)
            
            html = html .. "|-\n"
            html = html .. "| " .. rangeLabel .. "\n"
            html = html .. "| \n"
            html = html .. "| \n"
            html = html .. "| " .. dateDisplay .. "\n"
        end
    end

    return html
end

return p