Actions

Module

JourneySystem: Difference between revisions

From Dune Awakening DB

Created page with "-- Module:JourneySystem (Optimized for Template Data Fetching) -- Handles formatting and utility functions only -- Data fetching is done in templates for better caching local p = {} -- Default placeholder image local DEFAULT_JOURNEY_ICON = "https://dunedb.com/images/3/39/WikiPlaceholder.jpg" -------------------------------------------------- -- Helper: Get journey icon with fallback -------------------------------------------------- local function getJourneyIcon(iconP..."
 
mNo edit summary
Line 1: Line 1:
-- Module:JourneySystem (Optimized for Template Data Fetching)
-- Module:JourneySystem (Fixed)
-- Handles formatting and utility functions only
-- Handles formatting and utility functions only
-- Data fetching is done in templates for better caching
-- Data fetching is done in templates for better caching
Line 7: Line 7:
-- Default placeholder image
-- Default placeholder image
local DEFAULT_JOURNEY_ICON = "https://dunedb.com/images/3/39/WikiPlaceholder.jpg"
local DEFAULT_JOURNEY_ICON = "https://dunedb.com/images/3/39/WikiPlaceholder.jpg"
--------------------------------------------------
-- Helper: Get journey icon with fallback
--------------------------------------------------
local function getJourneyIcon(iconPath, size)
    size = size or "48px"
    -- Check for null, empty string, or "NULL" string
    if not iconPath or iconPath == "" or iconPath == "NULL" or iconPath == "null" then
        return string.format('<img src="%s" width="%s" height="%s" alt="Journey Icon">',
            DEFAULT_JOURNEY_ICON, size:match("(%d+)") or "48", size:match("(%d+)") or "48")
    end
    -- Check if it's already a full URL
    if iconPath:match("^https?://") then
        return string.format('<img src="%s" width="%s" height="%s" alt="Journey Icon">',
            iconPath, size:match("(%d+)") or "48", size:match("(%d+)") or "48")
    end
    -- Check if it's already a full File: reference
    if iconPath:match("^File:") then
        return string.format('[[%s|%s|link=]]', iconPath, size)
    end
    -- Check if it's a filename
    local fileTitle = mw.title.new("File:" .. iconPath)
    if fileTitle and fileTitle.exists then
        return string.format('[[File:%s|%s|link=]]', iconPath, size)
    else
        -- Fallback to placeholder
        return string.format('<img src="%s" width="%s" height="%s" alt="Journey Icon">',
            DEFAULT_JOURNEY_ICON, size:match("(%d+)") or "48", size:match("(%d+)") or "48")
    end
end
--------------------------------------------------
-- Function: getIcon
-- Public function to get journey icon
--------------------------------------------------
function p.getIcon(frame)
    local iconPath = frame.args[1] or ""
    local groupName = frame.args[2] or ""
    local size = frame.args[3] or "48px"
    if iconPath ~= "" then
        return getJourneyIcon(iconPath, size)
    else
        -- Use group-based fallback
        local groupIcons = {
            ['A New Beginning']          = 'Icon_Zone_NewBeginning.png',
            ['Vermillius Gap']          = 'Icon_Zone_Vermillius.png',
            ['Jabal Eifrit & Hagga Rift'] = 'Icon_Zone_Jabal.png',
            ['Find The Fremen']          = 'Icon_Trial_Fremen.png',
            ['Miscellaneous']            = 'Icon_Category_Standard.png',
            ['Factions']                = 'Icon_Category_Faction.png'
        }
        return getJourneyIcon(groupIcons[groupName], size)
    end
end


--------------------------------------------------
--------------------------------------------------
-- Function: getGroupIcon
-- Function: getGroupIcon
-- Get icon for journey group
-- Get icon for journey group - returns wiki markup
--------------------------------------------------
--------------------------------------------------
function p.getGroupIcon(frame)
function p.getGroupIcon(frame)
     local groupName = frame.args[1] or ""
     local groupName = frame.args[1] or ""
     local size     = frame.args[2] or "24px"
     local size = frame.args[2] or "24"
 
   
     local groupIcons = {
     local groupIcons = {
         ['A New Beginning']         = 'Icon_Zone_NewBeginning.png',
         ['A New Beginning'] = 'Icon_Zone_NewBeginning.png',
         ['Vermillius Gap']           = 'Icon_Zone_Vermillius.png',
         ['Vermillius Gap'] = 'Icon_Zone_Vermillius.png',
         ['Jabal Eifrit & Hagga Rift'] = 'Icon_Zone_Jabal.png',
         ['Jabal Eifrit & Hagga Rift'] = 'Icon_Zone_Jabal.png',
         ['Find The Fremen']         = 'Icon_Trial_Fremen.png',
         ['Find The Fremen'] = 'Icon_Trial_Fremen.png',
         ['Miscellaneous']           = 'Icon_Category_Standard.png',
         ['Miscellaneous'] = 'Icon_Category_Standard.png',
         ['Factions']                 = 'Icon_Category_Faction.png'
         ['Factions'] = 'Icon_Category_Faction.png'
    }
   
    local iconFile = groupIcons[groupName]
    if iconFile then
        -- Check if file exists
        local fileTitle = mw.title.new("File:" .. iconFile)
        if fileTitle and fileTitle.exists then
            return string.format('[[File:%s|%spx|link=]]', iconFile, size)
        end
    end
   
    -- Return emoji fallback for now
    local emojiIcons = {
        ['A New Beginning'] = '🏜️',
        ['Vermillius Gap'] = '⛰️',
        ['Jabal Eifrit & Hagga Rift'] = '🗿',
        ['Find The Fremen'] = '👁️',
        ['Miscellaneous'] = '📜',
        ['Factions'] = '🏛️'
     }
     }
 
   
     return getJourneyIcon(groupIcons[groupName], size)
     return emojiIcons[groupName] or '📍'
end
end


--------------------------------------------------
--------------------------------------------------
-- Function: buildJourneyJSON
-- Function: getJourneyBackground
-- Builds JSON from template data
-- Get background image URL for journey card
--------------------------------------------------
--------------------------------------------------
function p.buildJourneyJSON(frame)
function p.getJourneyBackground(frame)
     -- Data is supplied by template; just return placeholder for now
    local iconPath = frame.args[1] or ""
     return '{}'
   
end
     -- Check for null, empty string, or "NULL" string
 
     if not iconPath or iconPath == "" or iconPath == "NULL" or iconPath == "null" then
--------------------------------------------------
        return DEFAULT_JOURNEY_ICON
-- Function: escapeJson
    end
--------------------------------------------------
   
function p.escapeJson(frame)
    -- Check if it's already a full URL
    local text = frame.args[1] or ""
    if iconPath:match("^https?://") then
    text = text:gsub('"', '\\"')
        return iconPath
              :gsub('\n', '\\n')
    end
              :gsub('\r', '')
   
     return '"' .. text .. '"'
    -- Check if it's a File: reference - need to get the actual URL
    if iconPath:match("^File:") then
        iconPath = iconPath:gsub("^File:", "")
    end
   
    -- For file names, we need to construct the full URL
    -- This assumes your wiki files are at a standard path
     return string.format("https://dunedb.com/images/%s", iconPath)
end
end


--------------------------------------------------
--------------------------------------------------
-- Function: escapeHtml
-- Function: escapeHtml
-- Escape text for HTML attributes
--------------------------------------------------
--------------------------------------------------
function p.escapeHtml(frame)
function p.escapeHtml(frame)
     local text = frame.args[1] or ""
     local text = frame.args[1] or ""
    -- Escape quotes and HTML entities
     text = text:gsub('&', '&amp;')  -- Must be first
     text = text:gsub('&', '&amp;')  -- Must be first
              :gsub('"', '&quot;')
    text = text:gsub('"', '&quot;')
              :gsub("'", '&#39;')
    text = text:gsub("'", '&#39;')
              :gsub('<', '&lt;')
    text = text:gsub('<', '&lt;')
              :gsub('>', '&gt;')
    text = text:gsub('>', '&gt;')
     return text
     return text
end
end
Line 122: Line 91:
--------------------------------------------------
--------------------------------------------------
-- Function: formatObjectives
-- Function: formatObjectives
-- Format objectives with proper HTML structure
--------------------------------------------------
--------------------------------------------------
function p.formatObjectives(frame)
function p.formatObjectives(frame)
     local output, index = "", 1
    local journeyId = frame.args[1] or ""
 
     local output = ""
   
    -- The data comes from template, we just format it
    local index = 1
     while frame.args["obj_id_" .. index] do
     while frame.args["obj_id_" .. index] do
         local objId   = frame.args["obj_id_" .. index]
         local objId = frame.args["obj_id_" .. index]
         local objTitle = frame.args["obj_title_" .. index] or ""
         local objTitle = frame.args["obj_title_" .. index] or ""
         local objSeq   = frame.args["obj_seq_" .. index]   or index
         local objSeq = frame.args["obj_seq_" .. index] or index
       
         local collapsedClass = index > 1 and " collapsed" or ""
         local collapsedClass = index > 1 and " collapsed" or ""
 
       
         output = output .. string.format([[
         output = output .. string.format([[
<div class="objective-item%s">
<div class="objective-item%s">
Line 140: Line 114:
     </div>
     </div>
     <div class="objective-tasks">]], collapsedClass, objId, objSeq, objTitle)
     <div class="objective-tasks">]], collapsedClass, objId, objSeq, objTitle)
 
       
         -- Tasks
         -- Format tasks
         local taskIndex = 1
         local taskIndex = 1
         while frame.args["task_" .. index .. "_" .. taskIndex] do
         while frame.args["task_" .. index .. "_" .. taskIndex] do
             local taskDesc = frame.args["task_" .. index .. "_" .. taskIndex]
             local taskDesc = frame.args["task_" .. index .. "_" .. taskIndex]
             local taskQty = frame.args["task_qty_" .. index .. "_" .. taskIndex]
             local taskQty = frame.args["task_qty_" .. index .. "_" .. taskIndex]
 
           
             output = output .. string.format([[
             output = output .. string.format([[
         <div class="task-item">
         <div class="task-item">
             <div class="task-checkbox"></div>
             <div class="task-checkbox"></div>
             <div class="task-description">%s</div>]], taskDesc)
             <div class="task-description">%s</div>]], taskDesc)
 
           
             if taskQty and taskQty ~= "" then
             if taskQty and taskQty ~= "" then
                 output = output .. string.format('<div class="task-qty">%s pcs</div>', taskQty)
                 output = output .. string.format('<div class="task-qty">%s pcs</div>', taskQty)
             end
             end
 
           
             output = output .. '</div>\n'
             output = output .. '</div>\n'
             taskIndex = taskIndex + 1
             taskIndex = taskIndex + 1
         end
         end
 
       
         output = output .. [[
         output = output .. [[
     </div>
     </div>
</div>]]
</div>]]
       
         index = index + 1
         index = index + 1
     end
     end
 
   
     return output
     return output
end
end
Line 171: Line 146:
--------------------------------------------------
--------------------------------------------------
-- Function: formatMaterials
-- Function: formatMaterials
-- Format material list with icons
--------------------------------------------------
--------------------------------------------------
function p.formatMaterials(frame)
function p.formatMaterials(frame)
     local output, totalCount, idx = "", 0, 0
     local output = ""
 
    local totalCount = 0
     -- Count materials
    local index = 0
     while frame.args["mat_name_" .. (idx + 1)] do
   
     -- Count materials first
     while frame.args["mat_name_" .. (index + 1)] do
         totalCount = totalCount + 1
         totalCount = totalCount + 1
         idx        = idx + 1
         index = index + 1
     end
     end
 
   
     output = string.format([[
     output = string.format([[
<div class="materials-progress">
<div class="materials-progress">
Line 189: Line 167:
     <div class="material-category">
     <div class="material-category">
         <div class="material-category-title">Required Materials</div>]], totalCount)
         <div class="material-category-title">Required Materials</div>]], totalCount)
 
   
     -- Render each material
     -- Render materials
     for i = 1, totalCount do
     for i = 1, totalCount do
         local matName = frame.args["mat_name_" .. i] or ""
         local matName = frame.args["mat_name_" .. i] or ""
         local matQty = frame.args["mat_qty_" .. i] or "1"
         local matQty = frame.args["mat_qty_" .. i] or "1"
 
       
         -- Icon lookup
         -- Get icon
         local iconFile = matName:gsub("%s+", "_") .. "_-_Icon.png"
         local iconFile = matName:gsub("%s+", "_") .. "_-_Icon.png"
         local fileTitle = mw.title.new("File:" .. iconFile)
         local fileTitle = mw.title.new("File:" .. iconFile)
         local iconHtml = fileTitle and fileTitle.exists
         local iconHtml = ""
                          and string.format('[[File:%s|20px|link=]]', iconFile)
       
                          or '⚙️'
        if fileTitle and fileTitle.exists then
            iconHtml = string.format('[[File:%s|20px|link=]]', iconFile)
        else
            iconHtml = '⚙️'
        end


         -- *** fixed delimiter here ***
         -- *** fixed delimiter here ***

Revision as of 00:56, 26 May 2025

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

-- Module:JourneySystem (Fixed)
-- Handles formatting and utility functions only
-- Data fetching is done in templates for better caching

local p = {}

-- Default placeholder image
local DEFAULT_JOURNEY_ICON = "https://dunedb.com/images/3/39/WikiPlaceholder.jpg"

--------------------------------------------------
-- Function: getGroupIcon
-- Get icon for journey group - returns wiki markup
--------------------------------------------------
function p.getGroupIcon(frame)
    local groupName = frame.args[1] or ""
    local size = frame.args[2] or "24"
    
    local groupIcons = {
        ['A New Beginning'] = 'Icon_Zone_NewBeginning.png',
        ['Vermillius Gap'] = 'Icon_Zone_Vermillius.png',
        ['Jabal Eifrit & Hagga Rift'] = 'Icon_Zone_Jabal.png',
        ['Find The Fremen'] = 'Icon_Trial_Fremen.png',
        ['Miscellaneous'] = 'Icon_Category_Standard.png',
        ['Factions'] = 'Icon_Category_Faction.png'
    }
    
    local iconFile = groupIcons[groupName]
    if iconFile then
        -- Check if file exists
        local fileTitle = mw.title.new("File:" .. iconFile)
        if fileTitle and fileTitle.exists then
            return string.format('[[File:%s|%spx|link=]]', iconFile, size)
        end
    end
    
    -- Return emoji fallback for now
    local emojiIcons = {
        ['A New Beginning'] = '🏜️',
        ['Vermillius Gap'] = '⛰️',
        ['Jabal Eifrit & Hagga Rift'] = '🗿',
        ['Find The Fremen'] = '👁️',
        ['Miscellaneous'] = '📜',
        ['Factions'] = '🏛️'
    }
    
    return emojiIcons[groupName] or '📍'
end

--------------------------------------------------
-- Function: getJourneyBackground
-- Get background image URL for journey card
--------------------------------------------------
function p.getJourneyBackground(frame)
    local iconPath = frame.args[1] or ""
    
    -- Check for null, empty string, or "NULL" string
    if not iconPath or iconPath == "" or iconPath == "NULL" or iconPath == "null" then
        return DEFAULT_JOURNEY_ICON
    end
    
    -- Check if it's already a full URL
    if iconPath:match("^https?://") then
        return iconPath
    end
    
    -- Check if it's a File: reference - need to get the actual URL
    if iconPath:match("^File:") then
        iconPath = iconPath:gsub("^File:", "")
    end
    
    -- For file names, we need to construct the full URL
    -- This assumes your wiki files are at a standard path
    return string.format("https://dunedb.com/images/%s", iconPath)
end

--------------------------------------------------
-- Function: escapeHtml
-- Escape text for HTML attributes
--------------------------------------------------
function p.escapeHtml(frame)
    local text = frame.args[1] or ""
    -- Escape quotes and HTML entities
    text = text:gsub('&', '&amp;')  -- Must be first
    text = text:gsub('"', '&quot;')
    text = text:gsub("'", '&#39;')
    text = text:gsub('<', '&lt;')
    text = text:gsub('>', '&gt;')
    return text
end

--------------------------------------------------
-- Function: formatObjectives
-- Format objectives with proper HTML structure
--------------------------------------------------
function p.formatObjectives(frame)
    local journeyId = frame.args[1] or ""
    local output = ""
    
    -- The data comes from template, we just format it
    local index = 1
    while frame.args["obj_id_" .. index] do
        local objId = frame.args["obj_id_" .. index]
        local objTitle = frame.args["obj_title_" .. index] or ""
        local objSeq = frame.args["obj_seq_" .. index] or index
        
        local collapsedClass = index > 1 and " collapsed" or ""
        
        output = output .. string.format([[
<div class="objective-item%s">
    <div class="objective-header" data-objective-id="%s">
        <div class="objective-icon">%s</div>
        <div class="objective-title">%s</div>
        <div class="objective-progress">0/0</div>
    </div>
    <div class="objective-tasks">]], collapsedClass, objId, objSeq, objTitle)
        
        -- Format tasks
        local taskIndex = 1
        while frame.args["task_" .. index .. "_" .. taskIndex] do
            local taskDesc = frame.args["task_" .. index .. "_" .. taskIndex]
            local taskQty = frame.args["task_qty_" .. index .. "_" .. taskIndex]
            
            output = output .. string.format([[
        <div class="task-item">
            <div class="task-checkbox"></div>
            <div class="task-description">%s</div>]], taskDesc)
            
            if taskQty and taskQty ~= "" then
                output = output .. string.format('<div class="task-qty">%s pcs</div>', taskQty)
            end
            
            output = output .. '</div>\n'
            taskIndex = taskIndex + 1
        end
        
        output = output .. [[
    </div>
</div>]]
        
        index = index + 1
    end
    
    return output
end

--------------------------------------------------
-- Function: formatMaterials
-- Format material list with icons
--------------------------------------------------
function p.formatMaterials(frame)
    local output = ""
    local totalCount = 0
    local index = 0
    
    -- Count materials first
    while frame.args["mat_name_" .. (index + 1)] do
        totalCount = totalCount + 1
        index = index + 1
    end
    
    output = string.format([[
<div class="materials-progress">
    <span class="materials-progress-text">Materials Collected</span>
    <span class="materials-progress-count">0/%d</span>
</div>
<div class="materials-list">
    <div class="material-category">
        <div class="material-category-title">Required Materials</div>]], totalCount)
    
    -- Render materials
    for i = 1, totalCount do
        local matName = frame.args["mat_name_" .. i] or ""
        local matQty = frame.args["mat_qty_" .. i] or "1"
        
        -- Get icon
        local iconFile = matName:gsub("%s+", "_") .. "_-_Icon.png"
        local fileTitle = mw.title.new("File:" .. iconFile)
        local iconHtml = ""
        
        if fileTitle and fileTitle.exists then
            iconHtml = string.format('[[File:%s|20px|link=]]', iconFile)
        else
            iconHtml = '⚙️'
        end

        -- *** fixed delimiter here ***
        output = output .. string.format([=[
        <div class="material-item" data-material-index="%d">
            <div class="material-checkbox"></div>
            <div class="material-icon">%s</div>
            <div class="material-name">[[%s]]</div>
            <div class="material-qty">%s</div>
        </div>]=], i - 1, iconHtml, matName, matQty)
    end

    output = output .. [[
    </div>
</div>]]

    return output
end

return p