Module:OOOInfoBox: Difference between revisions
No edit summary |
mNo edit summary |
||
| (21 intermediate revisions by 2 users not shown) | |||
| Line 1: | Line 1: | ||
-- Module:OOOInfoBox | -- Module:OOOInfoBox | ||
local DATA = require('Module:OOO/Data') | local DATA = require('Module:OOO/Data') | ||
local p = {} | local p = {} | ||
-- --- | -- --------------------------------------------------------------------------- | ||
-- Helpers | |||
-- --------------------------------------------------------------------------- | |||
local function trim(s) | |||
return s and mw.text.trim(tostring(s)) or s | |||
end | |||
local function pick(args, data, key) | local function pick(args, data, key) | ||
local v = args[key] | local v = args[key] | ||
v = data and data[key] | if v and trim(v) ~= '' then return trim(v) end | ||
v = data and data[key] | |||
if v ~= nil and tostring(v) ~= '' then return v end | |||
end | end | ||
local function warn(msg) | local function warn(msg) | ||
return '<div class="mw-message-box mw-message-box-warning"><b>OOOInfoBox</b>: '..msg..'</div>' | return '<div class="mw-message-box mw-message-box-warning"><b>OOOInfoBox</b>: '..msg..'</div>' | ||
end | end | ||
local function render_image(name) | local function render_image(name) | ||
if not name or name == '' then return nil end | if not name or name == '' then return nil end | ||
return string.format('[[File:%s|center| | return string.format('[[File:%s|center|240px]]', mw.text.trim(name)) | ||
end | end | ||
-- | -- --------------------------------------------------------------------------- | ||
-- Units | |||
-- --------------------------------------------------------------------------- | |||
local U = { | local U = { | ||
m = ' m', | m = ' m', | ||
| Line 33: | Line 46: | ||
end | end | ||
-- | local function format_price(v) | ||
if not v then return nil end | |||
local n = tonumber(v) | |||
if not n then return v end | |||
local s = tostring(math.floor(n)) | |||
s = s:reverse():gsub("(%d%d%d)", "%1 "):reverse():gsub("^ ", "") | |||
return s .. ".-" | |||
end | |||
-- --------------------------------------------------------------------------- | |||
-- Row helpers | |||
-- --------------------------------------------------------------------------- | |||
local function label_with_tip(label, tip) | local function label_with_tip(label, tip) | ||
if not tip or tip == '' then return label end | if not tip or tip == '' then return label end | ||
| Line 39: | Line 67: | ||
end | end | ||
local function add_row(tbl, label, value, tip) | local function add_row(tbl, label, value, tip) | ||
if value ~= nil and tostring(value) ~= '' then | if value ~= nil and tostring(value) ~= '' then | ||
| Line 53: | Line 80: | ||
end | end | ||
-- --- | local function add_group(tbl, header, rows) | ||
local has = false | |||
for _, r in ipairs(rows) do | |||
if r and r[2] ~= nil and tostring(r[2]) ~= '' then | |||
has = true | |||
break | |||
end | |||
end | |||
if not has then return end | |||
add_group_header(tbl, header) | |||
for _, r in ipairs(rows) do | |||
if r then | |||
local label, value, tip = r[1], r[2], r[3] | |||
if value ~= nil and tostring(value) ~= '' then | |||
add_row(tbl, label, value, tip) | |||
end | |||
end | |||
end | |||
end | |||
-- --------------------------------------------------------------------------- | |||
-- Dimension builder | |||
-- --------------------------------------------------------------------------- | |||
local function join_dims(a, b, c, unit) | |||
local parts = {} | |||
if a then parts[#parts+1] = tostring(a) end | |||
if b then parts[#parts+1] = tostring(b) end | |||
if c then parts[#parts+1] = tostring(c) end | |||
if #parts == 0 then return nil end | |||
return table.concat(parts, ' × ') .. (unit or '') | |||
end | |||
-- --------------------------------------------------------------------------- | |||
-- Main renderer | |||
-- --------------------------------------------------------------------------- | |||
function p.building(frame) | function p.building(frame) | ||
local parent = frame:getParent() or frame | local parent = frame:getParent() or frame | ||
local args = parent.args or {} | local args = parent.args or {} | ||
local out = mw.html.create('div') | local out = mw.html.create('div') | ||
out:wikitext(frame:extensionTag('templatestyles', '', { src = 'Template:OOOInfoBox/styles.css' })) | |||
out:wikitext(frame:extensionTag( | |||
'templatestyles','',{ src = 'Template:OOOInfoBox/styles.css' } | |||
)) | |||
local domain = trim(args.type or args.domain or 'Buildings') | local domain = trim(args.type or args.domain or 'Buildings') | ||
local art = trim(args.art or args.artNumber or args.id) | local art = trim(args.art or args.artNumber or args.id) | ||
if not art or art == '' then | if not art or art == '' then | ||
out:wikitext(warn('Use |art=ART_NUMBER (e.g. 400113).')) | out:wikitext(warn('Use |art=ART_NUMBER (e.g. 400113).')) | ||
| Line 70: | Line 144: | ||
local data = DATA.get(domain, art) | local data = DATA.get(domain, art) | ||
if not data then | if not data then | ||
out:wikitext(warn(('No record for %s:%s.'):format(domain, art))) | out:wikitext(warn(('No record for %s:%s.'):format(domain, art))) | ||
| Line 75: | Line 150: | ||
end | end | ||
-- | -- ------------------------------------------------------------------------- | ||
-- Fields | |||
-- ------------------------------------------------------------------------- | |||
local title = pick(args, data, 'displayName') or ('Item '..art) | local title = pick(args, data, 'displayName') or ('Item '..art) | ||
local image = pick(args, data, 'image') | local image = pick(args, data, 'image') | ||
local caption = pick(args, data, 'description') or pick(args, data, 'caption') | local caption = pick(args, data, 'description') or pick(args, data, 'caption') | ||
local box = mw.html.create('table'):addClass('ooo-infobox') | local box = mw.html.create('table') | ||
:addClass('ooo-infobox') | |||
:addClass('ooo-infobox--' .. string.lower(domain)) | |||
-- optional width | |||
local w = tonumber(args.width) | |||
if w and w >= 240 and w <= 600 then | |||
box:css('width', w .. 'px') | |||
end | |||
-- alignment modifiers | |||
local align = trim(args.align) | |||
if align == 'left' then | |||
box:addClass('ooo-infobox--left') | |||
elseif align == 'center' then | |||
box:addClass('ooo-infobox--center') | |||
elseif align == 'sidebar' then | |||
box:addClass('ooo-infobox--sidebar') | |||
end | |||
-- additional classes | |||
local extra_class = trim(args.class) | |||
if extra_class then | |||
for c in mw.text.gsplit(extra_class,'%s+') do | |||
box:addClass(c) | |||
end | |||
end | |||
-- ------------------------------------------------------------------------- | |||
-- Title | -- Title | ||
-- ------------------------------------------------------------------------- | |||
box:tag('tr') | box:tag('tr') | ||
:tag('th') | :tag('th') | ||
:addClass('ooo-infobox__title') | |||
:attr('colspan','2') | |||
:wikitext(title) | |||
-- ------------------------------------------------------------------------- | |||
-- Image | -- Image | ||
-- ------------------------------------------------------------------------- | |||
local img = render_image(image) | local img = render_image(image) | ||
if img then | if img then | ||
box:tag('tr') | box:tag('tr') | ||
:tag('td') | :tag('td') | ||
:addClass('ooo-infobox__image') | |||
:attr('colspan','2') | |||
:wikitext(img) | |||
end | end | ||
if caption and caption ~= '' then | if caption and caption ~= '' then | ||
-- | -- Section title | ||
add_group_header(box, 'Description') | |||
-- Section content | |||
local tr = box:tag('tr') | |||
tr:tag('td') | |||
:attr('colspan','2') | |||
:css('text-align','left') | |||
:css('padding','4px 4px') | |||
:wikitext(caption) | |||
end | |||
-- ------------------------------------------------------------------------- | |||
-- General | |||
-- ------------------------------------------------------------------------- | |||
add_group(box,'General Information',{ | |||
{'Art Number', art}, | |||
{'Category', pick(args,data,'category')}, | |||
{'Subcategory',pick(args,data,'subcategory')}, | |||
{'Price', format_price(pick(args,data,'price'))}, | |||
}) | |||
-- ------------------------------------------------------------------------- | |||
-- Vehicle | |||
-- ------------------------------------------------------------------------- | |||
local function format_capacity(v) | |||
local n = tonumber(v) | |||
if not n then return v end | |||
return string.format("%.1f%s", n/1000, U.m3) | |||
end | |||
local function format_fuel_use(v) | |||
local n = tonumber(v) | |||
if not n or n < 0 then return nil end | |||
return tostring(n) .. " L/h" | |||
end | |||
local function format_fuel_capacity(v) | |||
local n = tonumber(v) | |||
if not n then return nil end | |||
return tostring(n) .. " L" | |||
end | |||
local function format_weight(v) | |||
local n = tonumber(v) | |||
if not n then return v end | |||
local s = tostring(math.floor(n)) | |||
s = s:reverse():gsub("(%d%d%d)", "%1 "):reverse():gsub("^ ", "") | |||
return s .. " kg" | |||
end | |||
add_group(box,'Vehicle Details',{ | |||
{'Unlock Level', pick(args,data,'level')}, | |||
{'Weight', format_weight(pick(args,data,'weight'))}, | |||
{'Capacity', format_capacity(pick(args,data,'capacity'))}, | |||
{'Fuel Tank', format_fuel_capacity(pick(args,data,'fuelCapacity'))}, | |||
{'Fuel Usage', format_fuel_use(pick(args,data,'fuelBaseUse'))}, | |||
}) | |||
-- ------------------------------------------------------------------------- | |||
-- Power | |||
-- ------------------------------------------------------------------------- | |||
add_group(box,'Power',{ | |||
{'Power', with_unit(pick(args,data,'power_kw'),U.kw)}, | |||
}) | |||
-- ------------------------------------------------------------------------- | |||
-- Performance | |||
-- ------------------------------------------------------------------------- | |||
if domain ~= 'Vehicles' then | |||
add_group(box,'Performance',{ | |||
{'Throughput (m³/h)', pick(args,data,'throughput_m3h')}, | |||
{'Capacity', pick(args,data,'capacity')}, | |||
}) | |||
end | |||
-- ------------------------------------------------------------------------- | |||
-- Input / Output | |||
-- ------------------------------------------------------------------------- | |||
add_group(box,'I/O',{ | |||
{'Conveyor inputs', pick(args,data,'beltInputs')}, | |||
{'Conveyor outputs', pick(args,data,'beltOutputs')}, | |||
{'Pipeline inputs', pick(args,data,'pipeInputs')}, | |||
{'Pipeline outputs', pick(args,data,'pipeOutputs')}, | |||
}) | |||
-- ------------------------------------------------------------------------- | |||
-- Dimensions | |||
-- ------------------------------------------------------------------------- | |||
local sx,sy,sz | |||
if data.size and type(data.size) == 'table' then | |||
sx,sy,sz = data.size.x, data.size.y, data.size.z | |||
end | end | ||
local size_w = pick(args,data,'size_width') or sx | |||
local size_w = pick(args, data, 'size_width') | local size_l = pick(args,data,'size_length') or sy | ||
local size_l = pick(args, data, 'size_length') | local size_h = pick(args,data,'size_height') or sz | ||
local size_h = pick(args, data, 'size_height') | local size_note = pick(args,data,'size_note') | ||
local size_note = pick(args, data, 'size_note') | |||
add_group(box,'Dimensions',{ | |||
{'Overall (W × H × L)', join_dims(size_w,size_l,size_h,U.m), 'Width × Height × Length'}, | |||
{'Note', size_note}, | |||
}) | |||
out:node(box) | out:node(box) | ||
return tostring(out) | return tostring(out) | ||
end | end | ||
return p | return p | ||