Module:JourneySystem
From Dune Awakening DB
Documentation for this module may be created at Module:JourneySystem/doc
-- 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(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
-- Get icon for journey group
--------------------------------------------------
function p.getGroupIcon(frame)
local groupName = frame.args[1] or ""
local size = frame.args[2] or "24px"
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
--------------------------------------------------
-- Function: buildJourneyJSON
-- Builds JSON from template data
--------------------------------------------------
function p.buildJourneyJSON(frame)
-- Data is supplied by template; just return placeholder for now
return '{}'
end
--------------------------------------------------
-- Function: escapeJson
--------------------------------------------------
function p.escapeJson(frame)
local text = frame.args[1] or ""
text = text:gsub('"', '\\"')
:gsub('\n', '\\n')
:gsub('\r', '')
return '"' .. text .. '"'
end
--------------------------------------------------
-- Function: escapeHtml
--------------------------------------------------
function p.escapeHtml(frame)
local text = frame.args[1] or ""
text = text:gsub('&', '&') -- Must be first
:gsub('"', '"')
:gsub("'", ''')
:gsub('<', '<')
:gsub('>', '>')
return text
end
--------------------------------------------------
-- Function: formatObjectives
--------------------------------------------------
function p.formatObjectives(frame)
local output, 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)
-- 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
--------------------------------------------------
function p.formatMaterials(frame)
local output, totalCount, idx = "", 0, 0
-- Count materials
while frame.args["mat_name_" .. (idx + 1)] do
totalCount = totalCount + 1
idx = idx + 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 each material
for i = 1, totalCount do
local matName = frame.args["mat_name_" .. i] or ""
local matQty = frame.args["mat_qty_" .. i] or "1"
-- Icon lookup
local iconFile = matName:gsub("%s+", "_") .. "_-_Icon.png"
local fileTitle = mw.title.new("File:" .. iconFile)
local iconHtml = fileTitle and fileTitle.exists
and string.format('[[File:%s|20px|link=]]', iconFile)
or '⚙️'
-- *** 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
