Module:Skill calc/eltGenerator

From RuneScape Classic Wiki
Jump to: navigation, search
Module documentation
This documentation is transcluded from Template:No documentation/doc. [edit] [purge]
This module does not have any documentation. Please consider adding documentation at Module:Skill calc/eltGenerator/doc. [edit]
Module:Skill calc/eltGenerator requires Module:Addcommas.
Module:Skill calc/eltGenerator requires Module:Coins.
Module:Skill calc/eltGenerator requires Module:Currency.
Module:Skill calc/eltGenerator requires Module:Number.
Module:Skill calc/eltGenerator requires Module:Tables.
Module:Skill calc/eltGenerator is required by Module:Skill calc.

-- <pre>
local commas        = require('Module:Addcommas')._add
local tables        = require('Module:Tables')
local coins         = require('Module:Coins')._amount
local currency      = require('Module:Currency')._amount
local numbers       = require('Module:Number')._round
local eltData       = {}

--[=[ 
        Note: Once all existing calculators have been converted, this Module will be cleaned
              up to remove any spaghetti code.

Generates a No profit, Purely Loss skill table
skills:
    Construction, Firemaking, Magic, Prayer
Inputs:
    T             data from caller
    unitExp       experience per iteration
    needed        required iterations for goal
    cost          cost per iteration
    eltArgs       additional parameters from caller
    productCost   product value per iteration
    remaining     xp required to reach target goal
    currLv        current level
returns: 
    Table of data using proper elts based on skill
--]=]
function eltData.generate_NoProfitLoss(frame)
    local T             = frame.args[1]
    local unitExp       = frame.args[2]
    local needed        = frame.args[3]
    local cost          = frame.args[4]
    local eltArgs       = frame.args[5]
    local productCost   = frame.args[6]
    local remaining     = frame.args[7]
    local currLv        = frame.args[8]
    local images, links

    -- Set default currency settings, then determine if alternative used
    local dispCurr = "int"
    if T.currency then dispCurr = T.currency end
    if eltArgs.disp == "Daemonheim" then cost = productCost end

    -- Set the icon and name
    images, links = setImgLnk(T, eltArgs)

    -- Will display the appropriate image if it's a Member/non-member item
    if T.members == 0 then  membersOnly     = "[[File:Member icon.png|16px|link=Pay-to-play]]"
    else                    membersOnly     = "[[File:Free-to-play icon.png|16px|link=Free-to-play]]" end

    -- Start here and build the elt down through conditionals
    elts =
    {
        images,
        links,
        cAlign(membersOnly)
    }

    -- Prayer needs an override since it is missing parts
    if eltArgs.skill == "Prayer" then
        table.insert(elts, 3, commas(unitExp, 1))
        table.insert(elts, 4, commas(needed))
        table.insert(elts, 5, coins(cost * needed))
        if not (eltArgs.disp == "Urns") then
            table.insert(elts, 6, coins(string.format("%.2f", (cost / unitExp), 1))) end
    else
        table.insert(elts, 3, numbers(T.level))
        table.insert(elts, 4, commas(unitExp, 1))
        if (eltArgs.skill == "Construction" and eltArgs.disp == "Milestones") then
            if T.coins then         table.insert(elts, 5, cAlign(coins(T.coins)))
            else                    table.insert(elts, 5, cAlign("-")) end
        else
            table.insert(elts, 5, commas(needed))
            if not (eltArgs.disp == "Char") then
                table.insert(elts, 6, createList(T.material, needed))
                if eltArgs.skill == "Magic" then
                    table.insert(elts, 7, coins(cost*needed))
                elseif not (eltArgs.skill == "Construction" and eltArgs.disp == "Other") then
                    if not (eltArgs.skill == "Firemaking" and
                        (eltArgs.disp == "Barbarian" or eltArgs.disp == "Other")) then
                        table.insert(elts, 7, printCoins(cost, dispCurr, currLv, T.level, true))
                        table.insert(elts, 8, printCoins(cost * needed, dispCurr, currLv, T.leve, truel))
                        table.insert(elts, 9, printCoins(cost / unitExp, dispCurr .. "-dec", currLv, T.level, true))
                    end
                end
            end
        end

        -- Check for flatpack exception
        -- Add bench image
        if eltArgs.disp == "Flatpacks" then
            table.insert(elts, 3, 
                imageLink2{
                    file=mw.text.split(T.bench, "<")[1],
                    image=mw.text.split(T.bench, "<")[1] .. "_icon",
                    alt=T.bench})
                --pLink(T.bench)
        end
    end

    return elts
end

--[=[
Generates a No Profit, No Loss skill table
skills:
    Agility, Invention, Slayer, Thieving
inputs:
    T             data from caller
    unitExp       experience per iteration
    needed        required iterations for goal
    eltArgs       additional parameters from caller
    remaining     xp required to reach target goal
    currLv        current level
returns:
    Table of data using proper elts based on skill
--]=]
function eltData.generate_NoProfitNoLoss(frame)
    local T             = frame.args[1]
    local unitExp       = frame.args[2]
    local needed        = frame.args[3]
    local eltArgs       = frame.args[4]
    local remaining     = frame.args[5]
    local currLv        = frame.args[6]
    local images, links

    -- Set the icon and name
    images, links = setImgLnk(T, eltArgs)

    -- Will display the appropriate image if it's a Member/non-member item
    if T.members == 0 then  membersOnly     = "[[File:Member icon.png|16px|link=Pay-to-play]]"
    else                    membersOnly     = "[[File:Free-to-play icon.png|16px|link=Free-to-play]]" end

    elts =
    {
        images,
        links,
        numbers(T.level),
        cAlign(membersOnly)
    }

    if eltArgs.skill == "Slayer" then
        if eltArgs.disp == "Assignments" or eltArgs.disp == "Monsters" then
            table.insert(elts, 4, T.level2)
            table.insert(elts, 5, commas(numbers(unitExp,1)))
            table.insert(elts, 6, printCoins(needed, "num", currLv, T.level2, true))
            if eltArgs.disp == "Assignments" then
                local modStrat = ""
                if     T.noStrat == 0 then          modStrat = "[[" .. T.name .. "/Strategies|Strategy]]"
                elseif T.noStrat == 1 then          modStrat = "[[" .. T.name .. T.strat .. "]]"
                elseif T.noStrat == 2 then          modStrat = "[[" .. T.strat .. "]]" end
                table.insert(elts, 7, modStrat)
            end
        end
    elseif eltArgs.skill == "Agility" then
        if not (eltArgs.disp == "Milestones" or eltArgs.disp == "Multiples" 
            or eltArgs.disp == "Other") then
            if T.multiXP then -- Testing
                table.insert(elts, 4, multiXPList(T.multiXP))
            else
                table.insert(elts, 4, commas(numbers(unitExp,1)))
            end
            table.insert(elts, 5, printCoins(needed, "num", currLv, T.level, true))
        end
    else
        table.insert(elts, 4, commas(numbers(unitExp,1)))
        table.insert(elts, 5, printCoins(needed, "num", currLv, T.level, true))
        if eltArgs.disp == "Sorceress Garden" then
            table.insert(elts, 6, createList(T.material, needed))
        elseif eltArgs.disp == "Safes" then
            table.insert(elts, 6, T.location)
        elseif eltArgs.disp == "Manufacturing - Ancient" then
        	table.insert(elts, 6, createList(T.material, needed))
        elseif eltArgs.disp == "Manufacturing" then
            table.insert(elts, 6, createList(T.material, needed))
            local techTree = "Human technology tree"
            local techTreeTitle = "Human"
            if T.techTree ~= nil then
                techTree = T.techTree
                if T.techTreeTitle ~= nil then techTreeTitle = T.techTreeTitle
                else techTreeTitle = techTree end
            end
            table.insert(elts, 7, "[[" .. techTree .. "|" .. techTreeTitle .. "]]")
        end
    end

    return elts
end

--[=[
Generates a potential Profit, potential Loss skill table
skills:
    Cooking, Crafting, Farming, Fletching, Herblore, Smithing, Summoning
inputs:
    T             data from caller
    unitExp       experience per iteration
    needed        required iterations for goal
    rawCost       ingredient cost per iteration
    eltArgs       additional parameters from caller
    productCost   product value per iteration
    remaining     xp required to reach target goal
    currLv        current level
returns:
    Table of data using proper elts based on skill
--]=]
function eltData.generate_ProfitLoss(frame)
    local T             = frame.args[1]
    local unitExp       = frame.args[2]
    local needed        = frame.args[3]
    local rawCost       = frame.args[4]
    local eltArgs       = frame.args[5]
    local productCost   = frame.args[6]
    local remaining     = frame.args[7]
    local currLv        = frame.args[8]
    local images, links, bonusExp
    local targetElt     = 6

    -- If alternative currencies are used, the Grand Exchange will not have information
    local materials = ""
    if not (T.currency == nil) and T.material then
        materials = cAlign(expandedList(T.material, needed), "left")
    elseif T.material then
        materials = createList(T.material, needed)
    elseif T.familiar then
        local altTitle = mw.text.split(T.familiar, "<")[1]
        if T.familiarTitle then altTitle = mw.text.split(T.familiarTitle, "<")[1] end

        materials = cAlign(peLink(mw.text.split(T.familiarIcon, "<")[1], mw.text.split(T.familiar, "<")[1], altTitle), "left")
    end

    -- Set default currency settings, then determine if alternative used
    local displayCurrency = "int"
    if T.currency then displayCurrency = T.currency end

    -- Set the icon and name
    images, links = setImgLnk(T, eltArgs)

    -- Will display the appropriate image if it's a Member/non-member item
    if T.members == 0 then  membersOnly     = "[[File:Member icon.png|16px|link=Pay-to-play]]"
    else                    membersOnly     = "[[File:Free-to-play icon.png|16px|link=Free-to-play]]" end

    elts =
    {
        images,
        links,
        numbers(T.level),
        commas(unitExp, 1),
        commas(needed)
    }

    if eltArgs.disp == "Forging" then
        table.insert(elts, 6, printCoins(productCost * needed, "int", currLv, T.level, true))
        table.insert(elts, 7, printCoins(productCost / unitExp, "dec", currLv, T.level, true))
        targetElt = 8
    else
        if eltArgs.skill == "Farming" then
            if eltArgs.disp == "Raising Animals" then
                bonusExp = generateNewXP(eltArgs) -- eltArgs.shiny, eltArgs.trait1, etc.
                elts = 
                    {
                        images,
                        links,
                        numbers(T.level),
                        commas(farmStats(eltArgs.stat1, eltArgs.stat2, T.stage1, bonusExp)),
                        commas(farmStats(eltArgs.stat1, eltArgs.stat2, T.stage2, bonusExp)),
                        commas(farmStats(eltArgs.stat1, eltArgs.stat2, T.stage3, bonusExp)),
                        commas(farmStats(eltArgs.stat1, eltArgs.stat2, T.stage4, bonusExp))
                    }
                unitExp        = farmStats(eltArgs.stat1, eltArgs.stat2, unitExp, bonusExp)
                needed         = tonumber(math.ceil(remaining / unitExp))
                table.insert(elts, 8, commas(unitExp, 1))
                table.insert(elts, 9, commas(needed))

            elseif not (eltArgs.disp == "Curing Animals" or eltArgs.disp == "Manure") then
                table.insert(elts, 6, materials)
                table.insert(elts, 7, printCoins(rawCost * needed, displayCurrency, currLv, T.level, true))
            end
        elseif eltArgs.disp == "Urns" then
            elts =
                {
                    images,
                    links,
                    commas(unitExp,1),
                    commas(needed),
                    printCoins((rawCost * needed), "int", currLv, T.level, true)
                }
        else
            table.insert(elts, 6, materials)

            if not (string.find(eltArgs.disp, "Dungeoneering - ") or (eltArgs.skill == "Smithing" and eltArgs.disp == "Equipment"
                and (eltArgs.equipment == "Kethsian" or eltArgs.equipment ==  "Masterwork (unfinished)" or eltArgs.equipment ==  "Obsidian"))) then
                if not (eltArgs.skill == "Cooking" and eltArgs.disp == "Dungeoneering") then
                    table.insert(elts, 7, printCoins(rawCost * needed, displayCurrency, currLv, T.level, true))

                    if not (eltArgs.skill == "Farming") then
                        table.insert(elts, 8, printCoins(productCost * needed, displayCurrency, currLv, T.level, true))
                        table.insert(elts, 9, printCoins((productCost - rawCost) * needed, displayCurrency, currLv, T.level, true))

                        -- Testing
                        if not (unitExp == 0) then
                            table.insert(elts, 10, printCoins((productCost - rawCost) / unitExp, displayCurrency .. "-dec", currLv, T.level, true))
                        else
                            table.insert(elts, 10, cAlign("-"))
                        end
                    end
                end
            end
        end

        if T.charm then
            table.insert(elts, 3, iLink(T.charm .. " charm", T.charm .. " charm"))
        end

        if eltArgs.skill == "Cooking" and (eltArgs.disp == "Dungeoneering" or eltArgs.disp == "Urns") then
            if eltArgs.disp == "Dungeoneering" then                                     targetElt = 7
            else                                                                        targetElt = 6 end
        elseif (eltArgs.skill == "Cooking" or eltArgs.skill == "Fletching" or eltArgs.skill == "Herblore" or eltArgs.skill == "Hunter" or eltArgs.skill == "Summoning")
            and string.find(eltArgs.disp, "Dungeoneering - ") then
            if eltArgs.disp == "Dungeoneering - Pouches" then                           targetElt = 8
            else                                                                        targetElt = 7 end
        elseif eltArgs.skill == "Summoning" then
            if eltArgs.disp == "Scrolls" then                                           targetElt = 11
            else                                                                        targetElt = 12 end
        elseif eltArgs.skill == "Farming" then
            if eltArgs.disp == "Raising Animals" then                                   targetElt = 10
            elseif eltArgs.disp == "Curing Animals" or eltArgs.disp == "Manure" then    targetElt = 6
            else                                                                        targetElt = 8 end
        else                                                                            targetElt = 11 end
    end

    table.insert(elts, targetElt, cAlign(membersOnly))

    return elts
end

--[=[
Generates a Purely Profit, No Loss skill table
skills:
    Divination, Fishing, Hunter, Mining, Runecrafting, Woodcutting
inputs:
    T             data from caller
    unitExp       experience per iteration
    needed        required iterations for goal
    rawCost       ingredient cost per iteration
    eltArgs       additional parameters from caller
    productCost   product value per iteration
    remaining     xp required to reach target goal
    currLv        current level
returns:
    Table of data using proper elts based on skill
--]=]
function eltData.generate_ProfitNoLoss(frame)
    local T             = frame.args[1]
    local unitExp       = frame.args[2]
    local needed        = frame.args[3]
    local rawCost       = frame.args[4]
    local eltArgs       = frame.args[5]
    local productCost   = frame.args[6]
    local remaining     = frame.args[7]
    local currLv        = frame.args[8]
    local images, links

    -- Set default currency settings, then determine if alternative used
    local setCurrency = "int"
    if T.currency then setCurrency = T.currency end

    -- Set the item's [link]
    -- Default with using the item's name
    local ourLink       = mw.text.split(T.name, "<")[1]
    local ourTitle      = mw.text.split(T.name, "<")[1]
    local equipmentLink = ""
    local materialList = ""

    -- Set the icon and name
    images, links = setImgLnk(T, eltArgs)

    -- Will display the appropriate image if it's a Member/non-member item
    if T.members == 0 then  membersOnly     = "[[File:Member icon.png|16px|link=Pay-to-play]]"
    else                    membersOnly     = "[[File:Free-to-play icon.png|16px|link=Free-to-play]]" end

    -- Check if an equipment link was specified
    if T.equipment then     equipmentLink   = mw.text.split(T.equipment, "<")[1] end

    -- Check if there are materials and create a list
    if T.material then      materialList    = createList(T.material,needed) end

    -- Default elts
    elts =
        {
            images,
            links,
            numbers(T.level),
            cAlign(membersOnly)
        }

    -- Put it all together
    if eltArgs.disp == "Urns" then
        table.insert(elts, 3, commas(unitExp, 1))
        table.insert(elts, 4, printCoins(needed, "num", currLv, T.level, true))
        table.insert(elts, 5, printCoins((rawCost * needed), "int", currLv, T.level, true))
    elseif eltArgs.skill == "Fishing" then
        local targetElt = 5
        if materialList == "" then materialList = cAlign("-") end
        table.insert(elts, 3, imageLink{file=equipmentLink, image=mw.text.split(T.equipment, "<")[1], alt=equipmentLink})
        if not (eltArgs.disp == "Deep Sea") then
            table.insert(elts, 4, materialList)
            targetElt = 6
        end
        table.insert(elts, targetElt, commas(unitExp,1))
        table.insert(elts, targetElt + 1, printCoins(needed, "num", currLv, T.level, true))

        if not (eltArgs.disp == "Dungeoneering") then
           table.insert(elts, targetElt + 2, printCoins(productCost * needed, "int", currLv, T.level, true))
           table.insert(elts, targetElt + 3, printCoins(rawCost * needed, "int", currLv, T.level, true))
            table.insert(elts, targetElt + 4, printCoins((productCost - rawCost) * needed, "int", currLv, T.level, true))
        end
    -- This section also accounts for base rune production multipliers
    elseif eltArgs.skill == "Runecrafting" then
        if eltArgs.disp == "Tiaras" then
            table.insert(elts, 3, commas(unitExp,1))
            table.insert(elts, 4, printCoins(needed, "num", currLv, T.level, true))
            table.insert(elts, 5, materialList)
            table.insert(elts, 6, printCoins(rawCost * needed, "int", currLv, T.level, true))
            table.insert(elts, 7, printCoins((productCost * needed), "int", currLv, T.level, true))
            table.insert(elts, 8, printCoins((productCost - rawCost ) * needed, "int", currLv, T.level, true))
        elseif eltArgs.disp == "Runespan - Free" or eltArgs.disp == "Runespan - Members" then
            table.insert(elts, 4, commas(unitExp,1))
            table.insert(elts, 5, commas(needed))
        else
            table.insert(elts, 4, commas(unitExp,1))
            table.insert(elts, 5, printCoins(needed, "num", currLv, T.level, true))
            table.insert(elts, 6, materialList)
            table.insert(elts, 7, printCoins(rawCost * needed, "int", currLv, T.level, true))
            table.insert(elts, 8, printCoins(
                    (productCost * needed) * levelMultiplier(ourIcon, tonumber(eltArgs.current)), "int", currLv, T.level, true))
            table.insert(elts, 9, printCoins(
                    ((productCost * levelMultiplier(ourIcon, tonumber(eltArgs.current))) - rawCost ) 
                        * needed, "int", currLv, T.level, true))
        end
    elseif eltArgs.skill == "Divination" then
        -- These allow for Cursed modification (tiered experience)
        local modifyExp    = 1
        local modifyNeeded = needed

        if T.name == "Cursed wisp" or T.name == "Cursed memory" then 
            modifyExp    = levelMultiplier(T.name, tonumber(eltArgs.current))
            modifyNeeded = tonumber(math.ceil(remaining / (unitExp * modifyExp)))
        elseif eltArgs.disp == "Boons" or T.boon == 0 or T.single == 0 then
            modifyNeeded = 1
        end
        --materialList needs to be recalculated with new value
        materialList = createList(T.material, modifyNeeded)

        if not (eltArgs.disp == "Other") then
            table.insert(elts, 4, commas(unitExp * modifyExp, 1))
            if eltArgs.disp == "Harvest" or eltArgs.disp == "" then
                table.insert(elts, 5, printCoins(modifyNeeded, "num", currLv, T.level, true))
                table.insert(elts, 6, printCoins((productCost * levelMultiplier(ourIcon, tonumber(eltArgs.current))) 
                    * modifyNeeded, "int", currLv, T.level, true))
            else
                local targetElt = 4
                if not (eltArgs.disp == "Boons") then
                    targetElt = targetElt + 1
                    if T.boon == 1 then         table.insert(elts, targetElt, cAlign("-"))
                    else                        table.insert(elts, targetElt, commas(modifyNeeded, 1)) end
                end
                table.insert(elts, (targetElt + 1), materialList)
                if not (eltArgs.disp == "Dungeoneering" or eltArgs.disp == "Memory-storage bots" or eltArgs.disp == 'Hall of Memories (2 tick)' or eltArgs.disp == 'Hall of Memories') then
                    table.insert(elts, (targetElt + 2), printCoins((0 - rawCost) * modifyNeeded, "int", currLv, T.level, true))
                end
            end
        end
    else
        elts =
        {
            images,
            links,
            numbers(T.level),
            commas(unitExp,1),
            commas(needed),
            cAlign(membersOnly)
        }

        -- Replace the above elts with:
        --table.insert(elts, 4, commas(unitExp, 1))
        --table.insert(elts, 5, printCoins(modifyNeeded, "num", currLv, T.level, true))

        if (eltArgs.skill == "Mining" and eltArgs.disp == "Gems") then
            table.insert(elts, 6, "[[" .. T.rock .. " gem rock|" .. T.rock .. "]]")
            table.insert(elts, 7, "[[" .. T.location .. "]]")
        elseif not (eltArgs.disp == "Dungeoneering" or 
            (eltArgs.skill == "Woodcutting" and eltArgs.disp == "Other") or (eltArgs.skill == "Hunter")) then
            table.insert(elts, 6, printCoins(productCost * needed, setCurrency, currLv, T.level, true))
        end

        if eltArgs.skill == "Hunter" then
            local targetElt = 6

            if (eltArgs.disp == "Nets and Sprites" or
               eltArgs.disp == "Deadfall and Pitfall" or
               eltArgs.disp == "Box Trapping" or
               eltArgs.disp == "Big Game Hunting") then
                if T.bait then      table.insert(elts, targetElt, pLink(T.bait))
                else                table.insert(elts, targetElt, cAlign("-")) end
                targetElt = targetElt + 1
            end

            if T.product then
                local currency = "Coins"
                if T.currency then currency = T.currency end
                table.insert(elts, targetElt, inlineProfit(productCost, needed, T.product, currency))
            elseif not (eltArgs.disp == "Big Game Hunting") then
                table.insert(elts, targetElt, cAlign("-"))
            end
        end
    end

    return elts
end

------------------------------------------------------
-------- Contemplating a global generator ------------
------------------------------------------------------

function eltData.generate_elts(frame)
    -- Don't worry about this function. I will be working on this over time to see if 
    -- everything can be generalized and merged into a single function and remain clear to remove repeated code
    -- Descriptive names make it more readily understandable

    --local membersOnly = '<sub title="Members only" style="cursor:help; margin-left:3px;">(m)</sub>' -- May be implemented differently

    -- These variables will always be passed through the initial call, even if they are not used
    -- (nil will be passed instead). Trying to use T and eltArgs more in code.
    local T                 = frame.args[1]     -- Individual item data
    local eltArgs           = frame.args[2]     -- Calculator data
    local actionExp         = frame.args[3]     -- Individual item experience with bonuses
    local actionsRequired   = frame.args[4]     -- Calculated iterations using actionExp
    local expRequired       = frame.args[5]     -- User experience data
    local rawCost           = frame.args[6]     -- Cost of materials
    local productCost       = frame.args[7]     -- Income from actions
    local eltTitles         = frame.args[8]     -- Array of elt titles
    local currentLevel      = frame.args[9]     -- Current level

    local imageExtension = ".png"
    if T.ext then imageExtension = T.ext end

    ---------------------------------------
    --- Begin overrides from skill data ---
    ---------------------------------------

    ------ Handle icons ------

        local icon = T.name
        -- Check for specified icon
        if T.icon ~= nil then icon = T.icon end
        -- Check for farming and make adjustments for seed icons
        if eltArgs.skill == "Farming" then 
            if T.seed ~= nil then icon = T.name ..  "_" .. T.seed end
        end

    ------ Handle title & link ------

        local link = T.name
        local linkTitle = T.name
        -- Check if a title was specified
        if T.title ~= nil then linkTitle = T.title end
        -- Setup titled link
        local multiplier = T.multiplier and ( ' × ' .. tostring(T.multiplier) ) or ''
        link  = '[[' .. T.name .. '|' .. linkTitle .. ']]' .. multiplier
        -- If specified, append additional wiki-links
        if T.extLink ~= nil then link = link .. " " .. T.extLink end -- (eg [[Voice of Seren]])
        -- Check for Members only
        local membersOnly
        if T.members == 0 then      membersOnly     = "[[File:Member icon.png|16px|link=Pay-to-play]]"
        else                        membersOnly     = "[[File:Free-to-play icon.png|16px|link=Free-to-play]]"
        end

        -- Set the actual icon image
        icon = imageLink2{file = T.name, alt = linkTitle, image = icon, iconSize = T.iconSize, showLink = false}

    ------ Handle materials ------

        local bench, familiar, materials, equipment = ""
        local currency = "coins"

        -- If alternative currencies are used, the Grand Exchange will not have information
        if not (T.currency == nil) and T.material then
            materials = cAlign(expandedList(T.material, actionsRequired), "left")
        elseif T.material ~= nil then
            materials = createList(T.material, actionsRequired)
        elseif T.familiar ~= nil then
            local familiar = mw.text.split(T.familiar, "<")[1]
            if T.familiarTitle ~= nil then familiar = mw.text.split(T.familiarTitle, "<")[1] end

            materials = cAlign(peLink(T.familiarIcon, mw.text.split(T.familiar, "<")[1], altTitle), "left")
        end

        -- Some items require the "materials" field to be preset to "-"
        if (eltArgs.skill == "Construction" and eltArgs.disp == "Other") or
               (eltArgs.skill == "Farming" and eltArgs.disp == "The Arc") or
               (eltArgs.skill == "Firemaking" and eltArgs.disp == "Other") or
               (eltArgs.skill == "Fishing" and (eltArgs.disp == "The Arc" or eltArgs.disp == "Popular" or 
               	                                eltArgs.disp == "Free-to-Play" or eltArgs.disp == "Members")) then
            materials = cAlign("-")
        end

        -- Set default currency settings, then determine if alternative used
        if T.currency ~= nil then currency = T.currency end

        -- Construction flatpacks
        if eltArgs.disp == "Flatpacks" then bench = imageLink2{file = T.bench, alt=T.bench} end

        -- Mostly for Fishing 
        if T.equipment ~= nil then
            local equipmentLink = T.equipment
            equipment = imageLink2{file = equipmentLink, image = T.equipment, alt = equipmentLink}
        end

    ---------------------------------------
    ---- End overrides from skill data ----
    ---------------------------------------

    -------------------------------
    --- Begin data calculations ---
    -------------------------------

    local grossIncome, grossCost, netIncome = 0
    local avgNet, avgCost = 0
    local modifiedExp     = 1   -- default value
    local modifiedNeeded  = actionsRequired   -- default value
    local stage1Exp       = 0
    local stage2Exp       = 0
    local stage3Exp       = 0
    local stage4Exp       = 0
    local profitExp       = 0

    if eltArgs.skill == "Runecrafting" and
       eltArgs.disp == "Runes" then

        grossIncome         = (productCost * actionsRequired) * levelMultiplier(T.name, currentLevel)
        netIncome           = ((productCost * levelMultiplier(T.name, currentLevel)) - rawCost ) * actionsRequired
    elseif eltArgs.skill == "Divination" and
        T.name == "Cursed wisp" or T.name == "Cursed memory" then

        modifiedExp     = levelMultiplier(T.name, currentLevel)
        modifiedNeeded  = tonumber(math.ceil(actionsRequired / (actionExp * modifiedExp)))
        actionExp       = modifiedExp
        actionsRequired = modifiedNeeded
    else
        local xpStat = 0
        local bonusExp = ""
        if eltArgs.skill == "Crafting" and T.name == "Protean hide" then
            actionExp       = levelMultiplier(T.name, currentLevel)
            actionsRequired = tonumber(math.ceil(expRequired / actionExp))
            materials       = createList(T.material, actionsRequired)
        elseif eltArgs.skill == "Farming" and eltArgs.disp == "Raising Animals" then
            bonusExp        = generateNewXP(eltArgs) -- eltArgs.shiny, eltArgs.trait1, etc.

            -- Player-owned farm animals (raising)
            stage1Exp       = farmStats(eltArgs.stat1, eltArgs.stat2, T.stage1, bonusExp)
            stage2Exp       = farmStats(eltArgs.stat1, eltArgs.stat2, T.stage2, bonusExp)
            stage3Exp       = farmStats(eltArgs.stat1, eltArgs.stat2, T.stage3, bonusExp)
            stage4Exp       = farmStats(eltArgs.stat1, eltArgs.stat2, T.stage4, bonusExp)
            actionExp       = farmStats(eltArgs.stat1, eltArgs.stat2, actionExp, bonusExp)
            actionsRequired = tonumber(math.ceil(expRequired / actionExp))
        elseif eltArgs.skill == "Farming" and eltArgs.disp == "Curing Animals" then
            bonusExp        = generateNewXP(eltArgs)
            actionExp       = farmStats(eltArgs.stat1, eltArgs.stat2, actionExp, bonusExp)
            actionsRequired = tonumber(math.ceil(expRequired / actionExp))
        elseif eltArgs.skill == "Hunter" and (eltArgs.disp == "Big Game Hunting" and eltArgs.bghxp == "1") then
            bonusExp        = generateNewXP(eltArgs)
            actionExp       = tonumber(actionExp + bonusExp)
            actionsRequired = tonumber(math.ceil(expRequired / actionExp))
        end
    end

    if rawCost ~= nil then
        grossCost   = rawCost * actionsRequired end

    if productCost ~= nil then
        grossIncome = productCost * actionsRequired end

    if (rawCost ~= nil and productCost ~= nil) then
        netIncome   = (productCost - rawCost) * actionsRequired 
    elseif rawCost ~= nil and rawCost ~= 0 then
        netIncome   = 0 - grossCost -- Force a negative; may not be needed
    elseif productCost ~= nil and grossIncome ~= 0 then
        netIncome   = grossIncome
    end

    avgNet = netIncome / actionsRequired

    if actionExp ~= 0 then -- For 0xp items
        avgCost     = netIncome / actionExp
        profitExp   = netIncome / actionExp
    end

    -------------------------------
    ---- End data calculations ----
    -------------------------------

    -------------------------------
    ---- Begin elt construction ---
    -------------------------------

    local generatedValues = 
            {
                icon            = icon,
                link            = link,
                bench           = bench,
                level           = numbers(T.level),
                members         = cAlign(membersOnly),
                actionExp       = commas(actionExp),
                stage1Exp       = commas(stage1Exp),
                stage2Exp       = commas(stage2Exp),
                stage3Exp       = commas(stage3Exp),
                stage4Exp       = commas(stage4Exp),
                actionsRequired = commas(actionsRequired),
                netIncome       = printCoins(netIncome, "int"),
                equipment       = equipment,
                materials       = materials,
                rawCost         = printCoins(rawCost, "int"),
                avgCost         = printCoins(avgCost, "dec"),
                grossCost       = printCoins(grossCost, "int"),
                grossIncome     = printCoins(grossIncome, "int"),
                profitExp       = printCoins(profitExp, "int"),
            }

    local elts = {}

    -- I think this is going to be the cleanest method of the ones we've tried.
    -- Not sure about performance-wise, since every item calls another round of
    --  looping through titles.
    for i, title in ipairs(eltTitles) do
        findEltData(title, generatedValues, elts)
    end

    -- These are special cases not worth including in the helper function
    if eltArgs.skill == "Summoning" and 
        eltArgs.disp ~= "Scrolls" then
        local charm = imageLink2{file = T.charm .. " charm"}
        table.insert(elts, 3, charm)                    -- Include summoning charms required
    elseif eltArgs.skill == "Hunter" then
        local targetElt = 6
        if (eltArgs.disp == "Nets and Sprites" or
            eltArgs.disp == "Deadfall and Pitfall" or
            eltArgs.disp == "Box Trapping" or
            eltArgs.disp == "Big Game Hunting") then
            if T.bait then table.insert(elts, targetElt, imageLink2{file = T.bait, showLink = true})    -- Include necessary bait
            else           table.insert(elts, targetElt, cAlign("-")) end  -- No bait necessary
            targetElt = 7
        end

        if not (eltArgs.disp == "Big Game Hunting") then
            if T.product then table.insert(elts, targetElt, imageLink2{file = T.product, showLink = true})
            else              table.insert(elts, targetElt, cAlign("-")) end  -- Nothing can be sold
        end
    end

    -------------------------------
    ----- End elt construction ----
    -------------------------------

    return elts
end

--------------------------------------
-------- Helper Functions ------------
--------------------------------------

-- This function is used to set the images and links for all skills (eventually)
function setImgLnk(T, eltArgs)
    local links, images

    -- Check for multiple images
    -- This occurs when multiple materials are required
    if T.multi then
        images  = 
                    imageLink{file=mw.text.split(T.multi[1], "<")[1],image=T.multi[1]},
                    imageLink{file=mw.text.split(T.multi[2], "<")[1],image=T.multi[2]}
                    --pLink(mw.text.split(T.multi[1], "<")[1]),
                    --pLink(mw.text.split(T.multi[1], "<")[2])
        links   =
                    '[[' .. mw.text.split(T.multi[1], "<")[1] .. ']]',
                    '[[' .. mw.text.split(T.multi[2], "<")[1] .. ']]'
    -- Single images only at then
    else
        -- Set the image location
        -- Default with using our page for the icon
        if T.noIcon == 0 then
            images = ""
        else
            local ourIcon = mw.text.split(T.name, "<")[1]

            -- Check for farming and make adjustments for seed icons
            if eltArgs.skill == "Farming" then 
                if T.seed then 
                    ourIcon = mw.text.split(T.name, "<")[1] ..  "_" .. mw.text.split(T.seed, "<")[1] 
                end
            end

            -- Check for flatpacks and adjust
            --if eltArgs.disp == "Flatpacks" then ourIcon = ourIcon .. " (flatpack)" end
            
            -- Add icon to end of construction items
            if eltArgs.skill == "Construction" and eltArgs.disp ~= "Flatpacks" and eltArgs.disp ~= "Supplies" then
            	ourIcon = mw.text.split(T.name, "<")[1] ..  "_icon"
            end

            -- Check if we specified an image location and make adjustments
            if T.image then ourIcon = mw.text.split(T.image, "<")[1] end
            if T.icon then ourIcon = mw.text.split(T.icon, "<")[1] end

            -- Hunter is a little different
            if eltArgs.skill == "Hunter" then
                if T.title and not T.icon  then
                    ourIcon = mw.text.split(T.title, "<")[1] 
                end
            end

            -- Check if the icon has been modified
            if T.iconSize then
                --images = imageLink{file=mw.text.split(T.name, "<")[1],image=ourIcon,iconSize=T.iconSize}
                images = iLink(ourIcon, mw.text.split(T.name, "<")[1], T.iconSize)
            else
                --images = imageLink{file=mw.text.split(T.name, "<")[1],image=ourIcon}
                images = iLink(ourIcon, mw.text.split(T.name, "<")[1])
            end
        end

        -- Set the item's [link]
        -- Default with using the item's name
        local ourTitle = mw.text.split(T.name, "<")[1]

        -- Check if we specified a page location
        if T.title then ourTitle = T.title end

        local multiplier = T.multiplier and ( ' × ' .. tostring(T.multiplier) ) or '' -- item amount produced per action
        links  = '[[' .. mw.text.split(T.name, "<")[1] .. '|' .. ourTitle .. ']]' .. multiplier
    end

    -- Add any non-linking text
    if T.sLink then links = T.sLink .. " " .. links end
    if T.eLink then links = links .. " " .. T.eLink end

    return images, links
end

-- Testing
function multiXPList(mess)
    local sentence = ""
    if not (mess == nil) then
        for i, v in ipairs(mess) do
            if (i%2) > 0 then
                if type(v) == "number" then
                    sentence = sentence .. " " .. v
                else
                    sentence = sentence .. " " .. v -- not needed?
                end
            else
                if i == table.getn(mess) then
                    sentence = sentence .. ": '''" .. v .. "'''"
                else
                    sentence = sentence .. ": '''" .. v .. "'''<br />"
                end
            end        
        end
        sentence = cAlign(sentence)
    else
        sentence = cAlign("-")
    end

    return sentence
end

-- ##Antiquated; needs to be phased out for pLink or peLink
function imageLink(params)
    local ext = ".png"
    local iconSize = nil
    if params.iconSize and params.iconSize > 0 then iconSize = params.iconSize end
    if params.ext then ext = params.ext end
    -- param.iconSize sets icon size if using a non-icon sized image.

    if params.alt then
        if params.image == "Bench with lathe" then
            return '[[File:Bench with lathe icon' .. ext .. '|link=' .. params.file .. '|' .. params.file .. ']]'
        elseif (iconSize) then
            return '[[File:' .. params.image .. ext .. '|' .. iconSize .. '|link=' .. params.file .. '|' .. params.alt .. ']]'
        else
            return '[[File:' .. params.image .. ext .. '|link=' .. params.file .. '|' .. params.alt .. ']]'
        end
    elseif not (iconSize == nil) then
        return '[[File:' .. params.image .. ext .. '|' .. iconSize .. 'px|link=' .. params.file .. '|' .. params.file .. ']]'
    else
        return '[[File:' .. params.image .. ext .. '|link=' .. params.file .. '|' .. params.file .. ']]'
    end
end -- imageLink

function imageLink2(params)
    local ext = ".png"
    local file, img, alt, size
    local showLink = false
                                file = params.file          -- default (required)
    if params.image then         img = params.image         -- set image if different from file
    else                         img = file end
    if params.ext then           ext = params.ext end
    if params.alt then           alt = params.alt end
    if params.iconSize then     size = params.iconSize end  -- resize image, if required
    if params.showLink then showLink = params.showLink end  -- show link after image, if required

    local                               ret = "[[File:"
    if img == "Bench with lathe" then   ret = ret .. "Bench with lathe icon" .. ext
    else                                ret = ret .. img .. ext end
    if size then                        ret = ret .. "|" .. size .. "px" end
                                        ret = ret .. "|link=" .. file .. "|" .. file
    if alt then                         ret = ret .. "|" .. alt end
                                        ret = ret .. "]]"

    -- Set link, if necessary
    if showLink == true then            ret = ret .. " [["
        if params.file then             ret = ret .. file end
        if params.alt then              ret = ret .. "|" .. alt end
                                        ret = ret .. "]]"
    end

    return ret
end

-- Displays materials in a list, while aligning the text accordingly
function createList(mess,a)
    local sentence = ""
    if not (mess == nil) then
        for i, v in ipairs(mess) do
            if (i%2) > 0 then
                if type(v) == "number" then
                	local _amt = v*a
                	if _amt > 100 then
                		_amt = math.ceil(_amt)
                	elseif not (_amt < 0.1) then
                		_amt = math.ceil(_amt * 100) / 100
                	end
                    sentence = "" .. sentence .. " " .. commas( _amt ) 
                else
                    sentence = "" .. sentence .. " " .. v
                end
            else
                if i == table.getn(mess) then
                    sentence = sentence .. " " .. imageLink2{file=v, showLink=true}
                    --sentence = sentence .. " " .. pLink(v)
                else
                    sentence = sentence .. " " .. imageLink2{file=v, showLink=true} .. "<br />"
                    --sentence = sentence .. " " .. pLink(v) .. "<br />"
                end
            end
        end
        sentence = cAlign(sentence, "left")
    else
        sentence = cAlign("-")
    end

    return sentence
end -- createList

-- This function is used for alternative currencies
-- ##Antiquated; should be phased out for mw.text.split usage
function expandedList(mess, a)
    local sentence = ""
    local follower = 0
    for i, v in ipairs(mess) do
        if type(v) == "number" then
            if follower == 0 then
                sentence = "" .. sentence .. " " .. commas( v * a ) 
                follower = 1
            else follower = 0 end
        else
            local parts = explode(",", v)
            local image = v
            local link = v
            if table.getn(parts) > 1 then
                image = parts[1]
                link = parts[2] end
            
            if i == table.getn(mess) then
                sentence = sentence .. " " .. peLink(image,link,link)
            else
                sentence = sentence .. " " .. peLink(image,link,link) .. "<br />"
            end
        end
    end

    return sentence
end

-- This is a simplified implementation of Template:Plink
function pLink(a)
    return "[[File:" .. a .. ".png|link=" .. a .. "]]&nbsp;[[" .. a .. "|" .. a .. "]]"
end -- plink

-- An extended implementation of pLink
function peLink(file, link, title)
    return "[[File:" .. file .. ".png|link=" .. link .. "]]&nbsp;[[" .. link .. "|" .. title .. "]]"
end -- pelink
 
-- This is an image-only implementation of peLink (can be temporary or permanent)
function iLink(file, link, size)
    --if link == nil then link = file end
    if size then    return '[[File:' .. file .. '.png|' .. size .. 'px|link=' .. link .. ']]'
    else            return '[[File:' .. file .. '.png|link=' .. link .. ']]' end
end -- iLink

function explain(message)
    local ret = mw.html.create('span'):css({['color'] = "#15f", ['border-bottom'] = "dotted 1px black", ['cursor'] = 'help'}):attr("title", message):wikitext("?")
    return "[" .. tostring(ret) .. "]"
end -- explain

-- This takes the amount of coins needed to display in table, 
--   but filters out 0s to make untradeables look better.
-- This function utilizes Module:Currency for alternative currency handling
function printCoins(amount, category, currLv, reqLv, isElt)
    --currLv = current level, reqLv = required level
    -- This will hide both zero-values and anything over the current level
    local ret
    local amt = amount
    local cls = nil
    if currLv == nil then currLv = 0 end
    if reqLv  == nil then reqLv  = 0 end

    if currLv >= reqLv and amount ~= 0 then
        if category == "dec" then               ret = coins(string.format("%.2f", amount, 1))
        elseif category == "int" then           ret = coins(amount, 1)
        elseif category == "int-dec" then       ret = coins(string.format("%.2f", amount, 1))
        elseif category == "chimes-dec" then    ret = currency(string.format("%.2f", amount, 1), "chimes")
        elseif category == "chimes" then        ret = currency(amount, "chimes")
        elseif category == "rusty-dec" then     ret = currency(string.format("%.2f", amount, 1), "rusty")
        elseif category == "rusty" then         ret = currency(amount, "rusty")
        elseif category == "num" then           ret = commas(amount)
        end
    else
        ret = cAlign("-")
        amt = -1000000000
        cls = 'sortbottom'
    end
    if isElt then
        return { text = ret, attr = { ['data-sort-value'] = amt }, class = cls }
    else
        return ret
    end
end

function generateNewXP(eltArgs)
    local shiny, trait1, trait2, trait3
    local bonusExp = 0
    local skill    = eltArgs.skill
    local disp     = eltArgs.disp
    local age      = eltArgs.age

    if skill == "Farming" then
        if disp == "Raising Animals" then
            shiny    = eltArgs.shiny
            trait1   = eltArgs.trait1
            trait2   = eltArgs.trait2
            trait3   = eltArgs.trait3

            if shiny  == "1" then               bonusExp = (10 / 100) end
            if trait1 == "Giver" then           bonusExp = bonusExp + (3 / 100) end
            if trait2 == "Giver" then           bonusExp = bonusExp + (3 / 100) end
            if trait3 == "Giver" then           bonusExp = bonusExp + (3 / 100) end

            if trait1 == "Limited Efficiency" 
                or trait1 == "Taker" then       bonusExp = bonusExp - (3 / 100) end
            if trait2 == "Limited Efficiency" 
                or trait2 == "Taker" then       bonusExp = bonusExp - (3 / 100) end
            if trait3 == "Limited Efficiency" 
               or trait3 == "Taker" then        bonusExp = bonusExp - (3 / 100) end

            if trait3 == "Exalted" then         bonusExp = bonusExp + (3 / 100) end
            if trait3 == "Nice but Dim" then    bonusExp = bonusExp + (14.4 / 100) end
            bonusExp = bonusExp + 1
        elseif disp == "Curing Animals" then
            if     age == "Baby" then           bonusExp = bonusExp + (5 / 1000)
            elseif age == "Adolescent" then     bonusExp = bonusExp + (75 / 10000)
            elseif age == "Adult" then          bonusExp = bonusExp + (15 / 1000)
            elseif age == "Elder" then          bonusExp = bonusExp + (45 / 10000) end

            --[=[
            -- Requires bonus XP %
            if trait3 == "Freak of Nature" then bonusExp = bonusExp + (x / 100) end
            --]=]
        end
    -- Adds 250xp (each) for building (4), arming (3), and baiting (1) the traps
    elseif skill == "Hunter" then            bonusExp = 2000
    end

    return bonusExp
end

-- Center the input (can be removed if there's an easier way to do this)
function cAlign(txtValue, orient)
    local ret

    if     orient == "left" then    ret = "<div style='text-align:left'>" .. txtValue .. "</div>"
    elseif orient == "right" then   ret = "<div style='text-align:right'>" .. txtValue .. "</div>"
    else                            ret = "<div style='text-align:center'>" .. txtValue .. "</div>"
    end

    return ret
end

function farmStats(stat1, stat2, xp, bXp)
    local ret = 10
    if stat1 ~= nil and stat2 ~= nil then
         ret = math.ceil((stat1 + stat2) / 2)
         if ret < 10 then ret = 10 end -- cannot be below 10
        ret = numbers((((xp * ret) / 100) * bXp), 1)
    else
        ret = numbers((((xp * 100) / 100) * bXp), 1)
    end

    return ret
end
--[[ levelMultiplier function
--      input:
--              item    :: key being searched
--              level   :: subject's relevant level
--      output:
--              Returns a base multiplier to modify experience or production levels depending
--               on the item being searched. Most items refer to multiple rune production,
--               but 'cursed' versions within divination give tiered experience.

--        Move to it's own Module?
--]]
function levelMultiplier(item, level)
    local ret = 1

    if item == "Air rune" then
        if     level >= 99 then ret = 10 
        elseif level >= 88 then ret = 9
        elseif level >= 77 then ret = 8
        elseif level >= 66 then ret = 7
        elseif level >= 55 then ret = 6
        elseif level >= 44 then ret = 5
        elseif level >= 33 then ret = 4
        elseif level >= 22 then ret = 3
        elseif level >= 11 then ret = 2 end

    elseif item == "Mind rune" then
        if     level >= 112 then ret = 9
        elseif level >= 98 then ret = 8
        elseif level >= 84 then ret = 7
        elseif level >= 70 then ret = 6
        elseif level >= 56 then ret = 5
        elseif level >= 42 then ret = 4
        elseif level >= 28 then ret = 3
        elseif level >= 14 then ret = 2 end

    elseif item == "Water rune" then
        if     level >= 114 then ret = 7
        elseif level >= 95 then ret = 6
        elseif level >= 76 then ret = 5
        elseif level >= 57 then ret = 4
        elseif level >= 38 then ret = 3
        elseif level >= 19 then ret = 2 end

    elseif item == "Earth rune" then
        if     level >= 104 then ret = 5
        elseif level >= 78 then ret = 4
        elseif level >= 52 then ret = 3
        elseif level >= 26 then ret = 2 end

    elseif item == "Fire rune" then
        if     level >= 105 then ret = 4
        elseif level >= 70 then ret = 3
        elseif level >= 35 then ret = 2 end

    elseif item == "Body rune" then
        if     level >= 92 then ret = 3
        elseif level >= 46 then ret = 2 end

    elseif item == "Cosmic rune" and level >= 118 then ret = 2
    elseif item == "Chaos rune"  and level >= 74 then ret = 2
    elseif item == "Astral rune" and level >= 82 then ret = 2
    elseif item == "Nature rune" and level >= 91 then ret = 2
    elseif item == "Law rune"    and level >= 110 then ret = 2
    elseif item == "Death rune"  and level >= 131 then ret = 2

    elseif item == "Armadyl rune" then
        if     level >= 99 then ret = 10
        elseif level >= 88 then ret = 9
        elseif level >= 77 then ret = 8
        elseif level >= 72 then ret = 7 end

    elseif item == "Blood rune" and level >= 154 then ret = 2

    elseif item == "Cursed wisp" then
        if     level >= 95 then ret = 12
        elseif level >= 90 then ret = 11
        elseif level >= 85 then ret = 10
        elseif level >= 80 then ret = 9
        elseif level >= 70 then ret = 8
        elseif level >= 60 then ret = 7
        elseif level >= 50 then ret = 6
        elseif level >= 40 then ret = 5
        elseif level >= 30 then ret = 4
        elseif level >= 20 then ret = 3
        elseif level >= 10 then ret = 2 end

    elseif item == "Cursed memory" then
        if     level >= 95 then ret = 64
        elseif level >= 90 then ret = 53
        elseif level >= 85 then ret = 46
        elseif level >= 80 then ret = 41
        elseif level >= 70 then ret = 36
        elseif level >= 60 then ret = 29
        elseif level >= 50 then ret = 22
        elseif level >= 40 then ret = 13
        elseif level >= 30 then ret = 8
        elseif level >= 20 then ret = 6
        elseif level >= 10 then ret = 5
        else                    ret = 4 end

    elseif item == "Protean hide" then
        if     level >= 100 then ret = 1        -- XP needed for levels 100+
        elseif level == 99 then  ret = 269.3
        elseif level == 98 then  ret = 266.8
        elseif level == 97 then  ret = 264.4
        elseif level == 96 then  ret = 262
        elseif level == 95 then  ret = 259.4
        elseif level == 94 then  ret = 257
        elseif level == 93 then  ret = 254.5
        elseif level == 92 then  ret = 252.2
        elseif level == 91 then  ret = 249.7
        elseif level == 90 then  ret = 247.2
        elseif level == 89 then  ret = 245
        elseif level == 88 then  ret = 242.4
        elseif level == 87 then  ret = 240
        elseif level == 86 then  ret = 237.5
        elseif level == 85 then  ret = 235
        elseif level == 84 then  ret = 232.6
        elseif level == 83 then  ret = 230.1
        elseif level == 82 then  ret = 227.7
        elseif level == 81 then  ret = 225.2
        elseif level == 80 then  ret = 222.7
        elseif level == 79 then  ret = 220.5
        elseif level == 78 then  ret = 217.9
        elseif level == 77 then  ret = 215.5
        elseif level == 76 then  ret = 213
        elseif level == 75 then  ret = 210
        elseif level == 74 then  ret = 208.1
        elseif level == 73 then  ret = 205.6
        elseif level == 72 then  ret = 203.3
        elseif level == 71 then  ret = 200.8
        elseif level == 70 then  ret = 198.4
        elseif level == 69 then  ret = 195.5
        elseif level == 68 then  ret = 193.4
        elseif level == 67 then  ret = 191.1
        elseif level == 66 then  ret = 188.6
        elseif level == 65 then  ret = 186.2
        elseif level == 64 then  ret = 183.7
        elseif level == 63 then  ret = 181.2
        elseif level == 62 then  ret = 178.8
        elseif level == 61 then  ret = 176.3
        elseif level == 60 then  ret = 174
        elseif level == 59 then  ret = 171.5
        elseif level == 58 then  ret = 169
        elseif level == 57 then  ret = 166.6
        elseif level == 56 then  ret = 164.1
        elseif level == 55 then  ret = 161.8
        elseif level == 54 then  ret = 159.3
        elseif level == 53 then  ret = 156.8
        elseif level == 52 then  ret = 154.4
        elseif level == 51 then  ret = 151.9
        elseif level == 50 then  ret = 149.5
        elseif level == 49 then  ret = 147
        elseif level == 48 then  ret = 144.7
        elseif level == 47 then  ret = 144.6
        elseif level == 46 then  ret = 139.7
        elseif level == 45 then  ret = 137.3
        elseif level == 44 then  ret = 134.8
        elseif level == 43 then  ret = 132.5
        elseif level == 42 then  ret = 132.5
        elseif level == 41 then  ret = 127.5
        elseif level == 40 then  ret = 125.1
        elseif level == 39 then  ret = 122.6
        elseif level == 38 then  ret = 120.2
        elseif level == 37 then  ret = 117.7
        elseif level == 36 then  ret = 115.2
        elseif level == 35 then  ret = 112.9
        elseif level == 34 then  ret = 110.4
        elseif level == 33 then  ret = 108
        elseif level == 32 then  ret = 105.5
        elseif level == 31 then  ret = 103
        elseif level == 30 then  ret = 100.6
        elseif level == 29 then  ret = 98.1
        elseif level == 28 then  ret = 95.8
        elseif level == 27 then  ret = 93.3
        elseif level == 26 then  ret = 90.9
        elseif level == 25 then  ret = 88.4
        elseif level == 24 then  ret = 85.9
        elseif level == 23 then  ret = 83.6
        elseif level == 22 then  ret = 81.1
        elseif level == 21 then  ret = 78.7
        elseif level == 20 then  ret = 76.2
        elseif level == 19 then  ret = 73.7
        elseif level == 18 then  ret = 71.3
        elseif level == 17 then  ret = 68.8
        elseif level == 16 then  ret = 66.5
        elseif level == 15 then  ret = 64
        elseif level == 14 then  ret = 61.5
        elseif level == 13 then  ret = 59.1
        elseif level == 12 then  ret = 56.6
        elseif level == 11 then  ret = 54.3
        elseif level == 10 then  ret = 51.8
        elseif level == 9 then   ret = 49.3
        elseif level == 8 then   ret = 46.9
        elseif level == 7 then   ret = 44.4
        elseif level == 6 then   ret = 42
        elseif level == 5 then   ret = 39.5
        elseif level == 4 then   ret = 37
        elseif level == 3 then   ret = 34.7
        elseif level == 2 then   ret = 32.2
        else                     ret = 29.8 end

    end

    return ret
end -- levelMultiplier

--[[ findEltData function
--   input:
--          EltTitle    :: A list of elts returned from /elts
--          EltValues   :: An object of calculated and formatted values
--          elts        :: A reference to the elts table for modification
--   output:
--          No values returned; this function directly updates the elts object
--           with the appropriate data.
--]]
function findEltData(EltTitle, EltValues, elts)

    if EltTitle == "" then
        table.insert(elts, EltValues.icon)
    elseif EltTitle == "Name" then
        table.insert(elts, EltValues.link)
    elseif EltTitle == "Level" then
        table.insert(elts, EltValues.level)
    elseif EltTitle == "Bench" then
        table.insert(elts, EltValues.bench)
    elseif EltTitle == "Tool" then
        table.insert(elts, EltValues.equipment)
    elseif EltTitle == "[[File:P2P-F2P icon.png|16px|link=|alt=Members]]" then
        table.insert(elts, EltValues.members)
    elseif EltTitle == "Egg to baby" then
        table.insert(elts, EltValues.stage1Exp)
    elseif EltTitle == "Baby to adolescent" then
        table.insert(elts, EltValues.stage2Exp)
    elseif EltTitle == "Adolescent to adult" then
        table.insert(elts, EltValues.stage3Exp)
    elseif EltTitle == "Adult to elder" then
        table.insert(elts, EltValues.stage4Exp)
    elseif EltTitle == "XP" or
            EltTitle == "Total XP" then
        table.insert(elts, EltValues.actionExp)
    elseif EltTitle == "# needed" then
        table.insert(elts, EltValues.actionsRequired)
    elseif EltTitle == "Bait" or
           EltTitle == "Materials" or
           EltTitle == "Seed" then
        table.insert(elts, EltValues.materials)
    elseif EltTitle == "Unit cost" then
        table.insert(elts, EltValues.rawCost)
    elseif EltTitle == "Cost" or
           EltTitle == "Profit" or
           EltTitle == "Profit/Loss" then
        table.insert(elts, EltValues.netIncome)
    elseif EltTitle == "Raw cost" then
        table.insert(elts, EltValues.grossCost)
    elseif EltTitle == "Product cost" then
        table.insert(elts, EltValues.grossIncome)
    elseif EltTitle == "XP cost" or
           EltTitle == "Income/XP" then
        table.insert(elts, EltValues.avgCost)
    elseif EltTitle == "Profit/XP" then
        table.insert(elts, EltValues.profitExp)
    end

end -- findEltData

-- From http://lua-users.org/wiki/SplitJoin
-- ##Antiquated; needs to be replaced throughout with mw.text.split
function explode(d,p)
   local t, ll
   t={}
   ll=0
   if(#p == 1) then
      return {p}
   end
   while true do
      l = string.find(p, d, ll, true) -- find the next d in the string
      if l ~= nil then -- if "not not" found then..
         table.insert(t, string.sub(p,ll,l-1)) -- Save it in our array.
         ll = l + 1 -- save just after where we found it for searching next time.
      else
         table.insert(t, string.sub(p,ll)) -- Save what's left in our array.
         break -- Break at end, as it should be, according to the lua manual.
      end
   end
   return t
end -- explode

--[[ inlineProfit function
--      input:
--              income  :: value of object
--              needed  :: number of actions required to meet goal
--              item    :: two-part item; (icon,link)
--              curr    :: currency being used
--      output:
--              Builds a string of pLinks with their corresponding total-costs
--               meant for an in-line view.
--]]
function inlineProfit(income, needed, item, curr)
    local sentence = ""
    local value = ""
    local parts = explode(",", item)
    local image = item
    local link = item

    if income ~= 0 then
        if curr == "Chimes" then
            value = value .. " : " .. currency(income * needed, "chimes")
        else 
            value = value .. " : " .. coins(income * needed, 1)
        end
    end

    if table.getn(parts) > 1 then
        image = parts[1]
        link = parts[2] end

        sentence = sentence .. " " .. peLink(image,link,link) .. value

    return sentence
end -- inlineProfit

--[[ findItem function
--      input:
--              list    :: a table of values
--              item    :: key being searched for
--      output:
--              Returns a boolean for presence within table
--]]
function findItem (list, item)
    local status = false
    for _,v in pairs(list) do
        if v == item then
            status = true
            break
        end
    end
    return status
end -- findItem

return eltData