Module:Infobox Element

From Oxygen Not Included Wiki
Jump to navigation Jump to search

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

local p = {}

local i18nde = require("Module:I18n/strings/elements")
local i18ndm = require("Module:I18n/strings/misc")
local _e = function(...) return i18nde["en"][(({...})[1])] end
local _m = function(...) return i18ndm["en"][(({...})[1])] end
local eleFromPagename = require("Module:ElementNames").elementFromPagename
local eleFromEleId = require("Module:ElementNames").elementFromElementId
local pagenameFromEle = require("Module:ElementNames").pagenameFromElement
local mergeArgs = require("Module:ProcessArgs").merge

local function _tempK(K) return mw.getCurrentFrame():expandTemplate{ title = 'Unit' , args = {K-273.15, 'temp'} } end
local function _allCapsNoSpace(str) return str:upper():gsub("%s+", "") end
local function _trim(str) return (str:gsub("^%s*(.-)%s*$", "%1")) end
local function _tagCode(t) return "STRINGS.MISC.TAGS." .. string.upper(t) end
local function _replaceStyledCaption(str) return str:gsub('<style="KKeyword">(.-)</style>', '[[%1]]') end
local function _useTemplate(template, arguments) return mw.getCurrentFrame():expandTemplate{ title = template, args = arguments } end
local function _isIn(x, t) if t then for _, e in ipairs(t) do if x == e then return true end end end return false end

local sterile = {'Carbon Dioxide', 'Chlorine Gas', 'Hydrogen Gas', 'Gold Gas', 'Rock Gas', 'Copper Gas', 'Steel Gas', 'Steam', 'Vacuum'}
local polluted = {'Polluted Oxygen', 'Phosphorus Gas'}
local sortOrder = {'specificHeatCapacity', 'thermalConductivity', 'hardness', 'strength', 'lightAbsorptionFactor', 'radiationAbsorptionFactor', 'radiationPer1000Mass', 'molarMass', 'defaultMass', 'maxMass'}
local labelAndFun = {
    specificHeatCapacity        = { 
                                    label = '[[Units#Specific_Heat_/_Heat_Capacity|Specific Heat Capacity]]', 
                                    fun = function(shc) return _useTemplate('Unit', {shc, 'shc'}) end
                                },
    thermalConductivity         = { label = '[[Thermal Conductivity]]', 
                                    fun = function(tc) return _useTemplate('Unit', {tc, 'tc'}) end
                                },
    hardness                    = {
                                    label = '[[Hardness]]', 
                                    fun = function(v) return _useTemplate('Hardness', {v}) end
                                },
    strength                    = {
                                    label = 'Strength',
                                    fun = function(v) return v end
                                },
    molarMass                   = {
                                    label = 'Molar Mass',
                                    fun = function(v) return _useTemplate('Unit', {v,'molar mass'}) end
                                },
    lightAbsorptionFactor       = {
                                    label = '[[Light]] Absorption Factor',
                                    fun = function(v) return 100*v .. "%" end
                                },
    radiationAbsorptionFactor   = {
                                    label = '[[Radiation]] Absorption Factor',
                                    fun = function(v) return 100*v .. "%" end
                                },
    radiationPer1000Mass        = {
                                    label = '[[Radiation|Rads per cycle]] per 1000kg',
                                    fun = function(v) if v == 0 then return nil end return v end
                                },
    defaultMass                 = {
                                    label = 'Default Mass',
                                    fun = function(v) if v == 0 or v == nil then return nil end return _useTemplate('Unit', {v*1000, 'mass'}) end
                                },
    maxMass                     = {
                                    label = 'Max  Mass',
                                    fun = function(v) if v == 0 or v == nil then return nil end return _useTemplate('Unit', {v*1000, 'mass'}) end
                                }
}


local function _extractChemicalSymbol(caption)
    if caption:sub(1, 1) == "(" then -- if caption starts with "(" 
        local match = caption:match("%b()") -- extract 
        if match then return match:sub(2, -2) end -- Remove the surrounding brackets
    end
    return nil
end

local function _getProperties(args, e)

    -- add state as link and as Category to page
    local retval = '[[:Category:'.. e.state .. '|'.. e.state .. ']], '
    if args.namespace == '' then return retval .. '[[Category:'.. e.state .. ']]' end

    if e.tags then
        for _, v in ipairs(e.tags) do
            if v ~= 'HideFromSpawnTool' and v ~= 'HideFromCodex' and v ~= 'EmitsLight' then 
                local tag = _m(_tagCode(v))
                retval = retval .. '[[:Category:'.. tag .. '|' .. tag ..']], '
                if args.namespace == '' then retval = retval .. '[[Category:'.. tag .. ']]' end
            end
        end
    end
    if _isIn(_trim(args.title), sterile) then retval = retval .. '[[Food#Atmospheres|Sterile Atmosphere]][[Category:Sterile Atmosphere]], ' end
    if _isIn(_trim(args.title), polluted) then retval = retval .. '[[Food#Atmospheres|Polluted Atmosphere]][[Category:Polluted Atmosphere]], ' end

    return retval:sub(1, -3) -- remove last ', '
end

local function _fetchPhaseTransitionData(eleID)
    local e = eleFromEleId(eleID)
    local retval = {}
    retval.name = pagenameFromEle(e)
    retval.state = e.state
    retval.SHC = e.specificHeatCapacity
    retval.TC = e.thermalConductivity
    return retval
end



local function _transitionName(e,t,k)
    local transitionName = {
        Solid = { 
            Liquid  = { high = 'melts' }, 
            Gas     = { high = 'sublimates' }, 
            Solid   = { high = 'cooks' } 
        },
        Liquid = { 
            Gas     = { low = 'exsolutes',   high = 'vaporizes' },
            Solid   = { low = 'freezes',     high = 'exsolutes' }
        },
        Gas = { 
            Liquid  = { low = 'condenses' },
            Solid   = { low = 'depositions' }
        }
    }
    if transitionName[e] then 
        if transitionName[e][t] then 
            if transitionName[e][t][k] then 
                return transitionName[e][t][k] .. ' into'
            end
        end
    end
    return 'transitions into'
end

local function _transitionTooltip(perc, name, shc)
    if perc == 100 then return _useTemplate('ElementTooltip', {name} ) .. ' (SHC: ' .. shc .. ')' end
    return perc .. '% ' .. _useTemplate('ElementTooltip', {name} ) .. ' (SHC: ' .. shc .. ')'
end

local function _addPhaseTransitionData(args, e)
    
    for _, i in ipairs({'highTempTransition', 'lowTempTransition'}) do

        if e[i .. 'OreId'] then
            local t = _fetchPhaseTransitionData(e[i .. 'Target'])
            local o = _fetchPhaseTransitionData(e[i .. 'OreId'])
            local transitionName = 'at ' .. _tempK(e[i:gsub('Transition', '')]) .. ' ' .. _transitionName(e.state, t.state, i:gsub('TempTransition', ''))

            args.general[#args.general+1] = transitionName
            args[transitionName] = 
                _transitionTooltip(100*(1-e[i .. 'OreMassConversion']), t.name, t.SHC) .. '<br>'
                .. _transitionTooltip(100*e[i .. 'OreMassConversion'], o.name, o.SHC) .. '<br>'

        elseif e[i .. 'Target'] then
            local t = _fetchPhaseTransitionData(e[i .. 'Target'])
            local transitionName = 'at ' .. _tempK(e[i:gsub('Transition', '')]) .. ' ' .. _transitionName(e.state, t.state, i:gsub('TempTransition', ''))

            args.general[#args.general+1] = transitionName
            args[transitionName] = 
                _transitionTooltip(100, t.name, t.SHC)
        end
    end

    return args
end


local function _primeElementData(pagename)
    local e = eleFromPagename(pagename)
    e.elementname = pagename

    -- fetch Description
    e.caption = _e("STRINGS.ELEMENTS." .. _allCapsNoSpace(e.elementId) .. ".DESC") or ""
    e.caption = _replaceStyledCaption(e.caption)

    if _extractChemicalSymbol(e.caption) then e.chem = _extractChemicalSymbol(e.caption) end

    if e.elementId == "Void" and not pagename == "Void" then 
        e.elementId = pagename 
        e.materialCategory = "none"
        e.caption = "This is either not an Element in ONI, or something went wrong with the Lua script."
    end
    return e
end

function p.hook(args)
    local name = _trim(args.title)
    local e = _primeElementData(name)
    
    args.subtitle = e.caption

    args.general = {}
    
    if e.state == 'Solid' or e.state == 'Gas' then
        if e.materialCategory then 
            args.general[#args.general+1] = 'Type'
            local type = _m(_tagCode(e.materialCategory))
            args.Type = '[[:category:'.. type .. '|' .. type .. ']]'
            if args.namespace == '' then args.Type = '[[Category:'.. type .. ']]' end
        end
    end
    
    if e.chem then 
        args.general[#args.general+1] = 'Chemical Symbol'
        args['Chemical Symbol'] = e.chem 
    end
    
    args = _addPhaseTransitionData(args, e)

    if e.sublimateId then
        args.general[#args.general+1] = 'sublimateId'
        local sublimated_element = eleFromEleId(e.sublimateId) 
        args['sublimateId'] = _useTemplate('ElementTooltip', {pagenameFromEle(sublimated_element)}) 
        if args['sublimates into'] then args['sublimateId'] = args['sublimates into'] end
        args['sublimateId_label'] = '[[Element Emission|sublimates]] into'
    end

    for _, k in ipairs(sortOrder) do
        if e[k] then
            args.general[#args.general+1] = k
            args[k .. '_label'] = labelAndFun[k].label
            args[k] = labelAndFun[k].fun(e[k])
        end
    end
    
    args.general[#args.general+1] = 'Properties'
    args['Properties'] = _getProperties(args, e)


    args.ID = '<code>' .. e.elementId .. '</code>'
    args.ID_label = '<code>elementId</code>'
    args['Localization string'] = '<code style="font-size:0.9em;">' .. e.localizationID .. '</code>'
    args['Localization string_label'] = '<code>localizationID</code>'

    return args
end

return p