Módulo:Farming rate calculator

De RuneScape Wiki
Ir para: navegação, pesquisa
Documentação do módulo
Esta documentação é transcluída de Predefinição:Sem documentação/doc. [editar] [atualizar]
Este módulo não possui nenhuma documentação. Por favor, considere adicionar uma documentação em Módulo:Farming rate calculator/doc. [editar]
Módulo:Farming rate calculator's a função main é invocada por Calculadora:Agricultura/Taxa.
Módulo:Farming rate calculator requer Módulo:ExchangeLite.
Módulo:Farming rate calculator requer Módulo:Experience.
Módulo:Farming rate calculator requer Módulo:Moedas.
Módulo:Farming rate calculator carrega dados de Módulo:Farm Data.

local p     = {}
local data  = mw.loadData('Módulo:Farm Data')
local gemw  = require('Módulo:ExchangeLite')
local xp    = require('Módulo:Experience').xp_at_level
local level = require('Módulo:Experience').level_at_xp
local coins = require('Módulo:Moedas')._amount

local lang  = mw.getContentLanguage() -- Number format helper function.

function p.main(frame)
    local args          = frame:getParent().args
    local farm_level    = tonumber(args.farm_level) or 1
    local farm_xp       = tonumber(args.farm_xp) or 1
    local target_lvl    = tonumber(args.target_level) or 0
    local target_xp     = tonumber(args.target_xp) or 0
    local base_method   = args.base_method or 'Agricultura'
    local plots         = args.plots or 'Tudo'
    local payment_show  = args.payment or 'Sim'                         -- Include or exclude the price of crop protection payments
    local animals       = args.animals or 'Criação'
    local regrown_b     = args.bushes or 'Não'                           -- Determine if bushes are to be regrown everytime
    local regrown_t     = args.trees or 'Não'                            -- Determine if fruit trees are to be regrown everytime
    local outfitpcs     = args.outfit                                   -- # of Master farmer outfit pieces worn
    local outfit        = data.outfit[outfitpcs] or 'Nenhum'              -- Bonus XP while harvesting crops
    local pofoutfit     = data.pof[outfitpcs] or 'Nenhum'                 -- Bonus XP for POF/RoOT
    local shiny         = tonumber(args.shiny) or 0
    local agetmp        = args.age or 'Bebe'
    local age           = data.age[agetmp]
    local farm_xp_boost = 1
    local trait1        = args.trait1 or 'Nenhum'
    local trait2        = args.trait2 or 'Nenhum'
    local trait3        = args.trait3 or 'Nenhum'
    local health        = args.health or 100
    local happiness     = args.happiness or 100
    local head          = args.head or 'Nenhum'
    local eyes          = args.eyes or 'Nenhum'
    local legfeet       = args.legfeet or 'Nenhum'
    local stomach       = args.stomach or 'Nenhum'
    local urntmp        = args.urns or 'Nenhum'
    local urns          = data.urns[urntmp] or 0
    local avatmp        = args.avatar or 'Nenhum'
    local avatar        = data.avatar[avatmp]                           -- Avatar buff
    local pcore         = tonumber(args.pulsecore) or 0                 -- Advanced pulse core (only xp boost)
    local ccore         = tonumber(args.cindercore) or 0                -- Cinder core (only xp boost)
    local dxp           = tonumber(args.dxp) or 0                       -- Double XP Weekend
    local customtmp     = tonumber(args.custom) or 0
    local custom        = customtmp / 100                               -- Custom XP boost
    local custom_farm   = tonumber(args.customfarm) or 0                -- Custom farming level boost (flat #)
    local bxp           = tonumber(args.bxp) or 0                       -- Bonus XP 
    local bxpnum        = tonumber(args.bxpnum) or 0                    -- Amount of bonus XP
    local xp            = 0
    local actionsRequired
    local regrown

    local coreboost = 1 + (pcore/100) + (ccore/100)

    -- Levels and targets
    local remaining = 0
    farm_level, farm_xp, target_lvl, target_xp, remaining = remainingExp(farm_level, farm_xp, target_lvl, target_xp)

    local has_target = false                                    -- Has a target
    if remaining > 0 then has_target = true end                 -- Has target true if remaing xp > 0

    local t = mw.html.create('table')
    t:addClass('wikitable sortable')
    if not has_target then
        -- Target goal equals or less than current level
        if base_method == 'Farming' then
            local r = t:tag('tr')
            r:tag('th')        :wikitext('')                    :addClass('unsortable')     :done()
             :tag('th')        :wikitext('Nome')                                            :done()
             :tag('th')        :wikitext('Nível')                                           :done()
--            if plots == 'All' then
--                r:tag('th')    :wikitext('Plot')                                            :done()
--            end
             :tag('th')        :wikitext('EXP')                                              :done()
             :tag('th')        :wikitext('Rendimento médio')                                       :done()
             --:tag('th')        :wikitext('Seed')                                            :done()
             :tag('th')        :wikitext('[[Arquivo:P2P-F2P ícone.png|30px|alt=Membros]]')      :done()
             :done()
        else    -- Player-owned farms
            if animals == 'Curing' then
                t:tag('tr')
                 :tag('th')    :wikitext('')                    :addClass('unsortable')     :done()
                 :tag('th')    :wikitext('Animal')                                          :done()
                 :tag('th')    :wikitext('Nível')                                           :done()
                 :tag('th')    :wikitext('EXP')                                              :done()
                 :tag('th')    :wikitext('[[Arquivo:P2P-F2P ícone.png|30px|alt=Membros]]')      :done()
                 :done()
            elseif animals == 'Manure' then
                t:tag('tr')
                 :tag('th')    :wikitext('')                    :addClass('unsortable')     :done()
                 :tag('th')    :wikitext('Nome')                                            :done()
                 :tag('th')    :wikitext('Nível')                                           :done()
                 :tag('th')    :wikitext('EXP')                                              :done()
                 :tag('th')    :wikitext('[[Arquivo:P2P-F2P ícone.png|30px|alt=Membros]]')      :done()
                 :done()
            else -- Raising
                t:tag('tr')
                 :tag('th')    :wikitext('')                    :addClass('unsortable')     :done()
                 :tag('th')    :wikitext('Animal')                                          :done()
                 :tag('th')    :wikitext('Nível')                                           :done()
                 :tag('th')    :wikitext('Ovo para bebe')                                     :done()
                 :tag('th')    :wikitext('Bebe para adolescente')                              :done()
                 :tag('th')    :wikitext('Adolescente para adulto')                             :done()
                 :tag('th')    :wikitext('Adulto para idoso')                                  :done()
                 :tag('th')    :wikitext('Total de EXP')                                        :done()
                 :tag('th')    :wikitext('[[Arquivo:P2P-F2P ícone.png|30px|alt=Membros]]')      :done()
                 :done()
            end
        end
    else -- Default
        if base_method == 'Farming' then
            local r = t:tag('tr')
            r:tag('th')    :wikitext('')                         :addClass('unsortable')    :done()
             :tag('th')    :wikitext('Nome')                                                :done()
             :tag('th')    :wikitext('Nível')                                               :done()
--            if plots == 'All' then
--                r:tag('th')    :wikitext('Plot')                                            :done()
--            end
            if plots == 'Habitat de Herbologia' or plots == 'Outras plantas' or plots == 'Árvores' then
                r:tag('th')    :wikitext('Canteiro')                                           :done()
            end
            r:tag('th')    :wikitext('EXP')                                                  :done()
             :tag('th')    :wikitext('Rendimento médio')                                           :done()
             :tag('th')    :wikitext('# necessário')                                            :done()
             :tag('th')    :wikitext('Semente')                                                :done()
            if not (plots == 'O Arco' or plots == 'Ervas') then
                r:tag('th'):wikitext('Pagamento')                                             :done()
            end
            r:tag('th')    :wikitext('Custo da semente')                                           :done()
             :tag('th')    :wikitext('Custo total')                                          :done()
             :tag('th')    :wikitext('Lucro/prejuízo')                                         :done()
             :tag('th')    :wikitext('[[Arquivo:P2P-F2P ícone.png|30px|alt=Membros]]')          :done()
             :done()
        else -- Player-owned farms
            if animals == 'Curing' then
                t:tag('tr')
                 :tag('th')    :wikitext('')                     :addClass('unsortable')    :done()
                 :tag('th')    :wikitext('Animal')                                          :done()
                 :tag('th')    :wikitext('Nível')                                           :done()
                 :tag('th')    :wikitext('EXP')                                              :done()
                 :tag('th')    :wikitext('# necessário')                                        :done()
                 :tag('th')    :wikitext('[[Arquivo:P2P-F2P ícone.png|30px|alt=Membros]]')      :done()
                 :done()
            elseif animals == 'Manure' then
                t:tag('tr')
                 :tag('th')    :wikitext('')                     :addClass('unsortable')    :done()
                 :tag('th')    :wikitext('Nome')                                            :done()
                 :tag('th')    :wikitext('Nível')                                           :done()
                 :tag('th')    :wikitext('EXP')                                              :done()
                 :tag('th')    :wikitext('# necessário')                                        :done()
                 :tag('th')    :wikitext('[[Arquivo:P2P-F2P ícone.png|30px|alt=Membros]]')      :done()
                 :done()
            else --Raising
                t:tag('tr')
                 :tag('th')    :wikitext('')                     :addClass('unsortable')    :done()
                 :tag('th')    :wikitext('Animal')                                          :done()
                 :tag('th')    :wikitext('Nível')                                           :done()
                 :tag('th')    :wikitext('Ovo para bebe')                                     :done()
                 :tag('th')    :wikitext('Bebe para adolescente')                              :done()
                 :tag('th')    :wikitext('Adolescente para adulto')                             :done()
                 :tag('th')    :wikitext('Adulto para idoso')                                  :done()
                 :tag('th')    :wikitext('Total de EXP')                                        :done()
                 :tag('th')    :wikitext('# necessário')                                        :done()
                 :tag('th')    :wikitext('[[Arquivo:P2P-F2P ícone.png|30px|alt=Membros]]')      :done()
                 :done()
            end
        end
    end

    for index, i in ipairs(data.farming) do
        local isplot = false
        if base_method == 'Agricultura' and (plots == 'Tudo' or plots == i.cat) then
            isplot = true
        elseif base_method == 'Player-owned Farm' and (animals == 'Tudo' or animals == i.cat) then
            isplot = true
        end

        if farm_level >= i.level and isplot or has_target and isplot and i.level <= target_lvl then
            local icon    = i.icon
            local name    = i.name
            local title   = i.title
            local imgSize = i.imgSize
            local level   = i.level

            -- Set icon
            if icon then    icon = '[[Arquivo:'.. icon .. '.png|link='.. name
            else            icon = '[[Arquivo:'.. name .. '.png|link='.. name end
            if imgSize then icon = icon .. '|' .. imgSize .. 'px' end
            icon = icon ..']]'

            -- Set link
            local link = '[[' .. name
            if title then   link = link .. '|' .. title end
            link = link .. ']]'


            local membersOnly
            if i.members == 0 then      membersOnly     = '[[Arquivo:P2P ícone.png|25px|link=Membros]]'
            else                        membersOnly     = '[[Arquivo:F2P ícone.png|25px|link=Jogadores gratuitos]]' end

            if base_method == "Agricultura" then
                local harvest  = 1
                local yieldAvg = 1
                local xp       = i.xp * (1 + (pcore/100))
                local hxp
                if i.harvest then harvest   = i.harvest  end -- XP earned from harvesting one item
                if i.yieldavg then yieldAvg = i.yieldavg end -- Average # of items per crop

                xp = xp + ((harvest * coreboost) * yieldAvg)

                if plots == 'Arbustos' then
                    regrown = regrown_b
                    if regrown == 'Não' then hxp = (harvest * coreboost) * yieldAvg end
                elseif plots == 'Árvores' then
                    regrown = regrown_t
                    if regrown == 'Não' then hxp = (harvest * coreboost) * yieldAvg end
                end

                -- Apply [Master] Farmer's Outfit bonus XP
                if outfitpcs == '5 Partes' then
                    xp = xp * 1.02
                    if hxp then hxp = math.ceil((hxp * 1.02) * 10) / 10 end
                end
                xp  = math.ceil(xp * 10) / 10

                if hxp then
                    actionsRequired = math.ceil((remaining - (xp + hxp)) / hxp) + 1
                    -- Subtract the full xp value (planting, checking & harvesting), then divide the remaining value by only the harvesting xp, and add 1 to the final value
                else
                    actionsRequired = math.ceil(remaining / xp)
                end

                local patch = 'Árvore'
                if i.patch then patch = i.patch end

                local mats = getMats(i, actionsRequired, plots, patch, outfitpcs, payment_show, regrown)

                if not has_target then
                    local rawCost         = 1
                    local r = t:tag('tr'):addClass(tr_class)
                    r:tag('td')      :wikitext(icon)                                                                :done()
                     :tag('td')      :wikitext(link)                            :css('text-align', 'center')        :done()
                     :tag('td')      :wikitext(level)                           :css('text-align', 'center')        :done()
--                    if plots == 'All' then
--                        r:tag('td')  :wikitext(i.cat)                           :css('text-align', 'center')        :done()
--                    end
                     :tag('td')      :wikitext(fnum(xp))                        :attr('data-sort-value', xp)        :done()
                     :tag('td')      :wikitext(yieldAvg)                        :css('text-align', 'center')        :done()
                     :tag('td')      :wikitext(membersOnly)                     :css('text-align', 'center')        :done()
                     :done()
                else
                    -- Row colors
                    local tr_class = 'table-bg-yellow sortbottom'
                    if i.level > target_lvl then
                        tr_class   = 'table-bg-red sortbottom'
                    elseif i.level <= farm_level then
                        tr_class   = 'table-bg-green'
                    end

                    if plots == 'Árvores' then
                        if i.patch then patch = patch .. ' árvore' end
                    end

                    local r = t:tag('tr'):addClass(tr_class)
                    r:tag('td')      :wikitext(icon)                                                                :done()
                     :tag('td')      :wikitext(link)                            :css('text-align', 'center')        :done()
                     :tag('td')      :wikitext(level)                           :css('text-align', 'center')        :done()
--                    if plots == 'All' then
--                        r:tag('td')  :wikitext(i.cat)                           :css('text-align', 'center')        :done()
--                    end
                    if plots == 'Habitat de Herbologia' or plots == 'Outras plantas' or plots == 'Árvores' then
                        r:tag('td')  :wikitext(patch)                           :css('text-align', 'center')        :done()
                    end
                    r:tag('td')      :wikitext(fnum(xp))                        :attr('data-sort-value', xp)        :done()
                     :tag('td')      :wikitext(yieldAvg)                        :css('text-align', 'center')        :done()
                     :tag('td')      :wikitext(fnum(actionsRequired))           :css('text-align', 'center')        :done()
                     :tag('td')      :wikitext(mats.display)                    :css('text-align', 'center')        :done()
                    if not (plots == 'O Arco' or plots == 'Ervas') then
                        r:tag('td')  :wikitext(mats.payment)                    :css('text-align', 'center')        :done()
                    end
                    r:tag('td')      :wikitext(mats.rawCost)                    :css('text-align', 'center')        :done()
                     :tag('td')      :wikitext(mats.cost)                       :css('text-align', 'center')        :done()
                     :tag('td')      :wikitext(mats.profit)                     :css('text-align', 'center')        :done()
                     :tag('td')      :wikitext(membersOnly)                     :css('text-align', 'center')        :done()
                     :done()
                end
            else -- Player-owned Farm
                xp  = i.xp
                if not has_target then
                    if animals == 'Curing' or animals == 'Manure' then
                        if     animals == 'Curing' then         xp = math.ceil(((xp * age) * pofoutfit) * 10) / 10
                        elseif animals == 'Manure' then         xp = math.ceil((xp * pofoutfit) * 10) / 10
                        end

                        local r = t:tag('tr'):addClass(tr_class)
                        r:tag('td')      :wikitext(icon)                                                         :done()
                         :tag('td')      :wikitext(link)                     :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(i.level)                  :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(xp))                 :attr('data-sort-value', xp)        :done()
                         :tag('td')      :wikitext(membersOnly)              :css('text-align', 'center')        :done()
                         :done()
                    else -- Raising
                        -- Set bonus XP
                        local bonusXP = getBonusXP(i, health, happiness, shiny, trait1, trait2, trait3)

                        -- Set variables & apply [Master] Farmer's Outfit bonus XP
                        local stage1xp = math.ceil((bonusXP.stage1xp * pofoutfit) * 10) / 10
                        local stage2xp = math.ceil((bonusXP.stage2xp * pofoutfit) * 10) / 10
                        local stage3xp = math.ceil((bonusXP.stage3xp * pofoutfit) * 10) / 10
                        local stage4xp = math.ceil((bonusXP.stage4xp * pofoutfit) * 10) / 10
                        local totalxp  = bonusXP.totalxp * pofoutfit

                        local r = t:tag('tr'):addClass(tr_class)
                        r:tag('td')      :wikitext(icon)                                                         :done()
                         :tag('td')      :wikitext(link)                     :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(i.level)                  :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(stage1xp))           :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(stage2xp))           :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(stage3xp))           :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(stage4xp))           :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(totalxp))            :attr('data-sort-value', totalxp)   :done()
                         :tag('td')      :wikitext(membersOnly)              :css('text-align', 'center')        :done()
                         :done()
                    end
                else
                    -- Row colors
                    local tr_class = 'table-bg-yellow sortbottom'
                    if i.level > target_lvl then
                        tr_class   = 'table-bg-red sortbottom'
                    elseif i.level <= farm_level then
                        tr_class   = 'table-bg-green'
                    end

                    local r = t:tag('tr'):addClass(tr_class)
                    if animals == 'Curing' or animals == 'Manure' then
                        if     animals == 'Curing' then     xp = math.ceil(((xp * age) * pofoutfit) * 10) / 10
                        elseif animals == 'Manure' then     xp = math.ceil((xp * pofoutfit) * 10) / 10 end
                        actionsRequired = math.ceil(remaining / (xp * farm_xp_boost))

                        r:tag('td')      :wikitext(icon)                                                         :done()
                         :tag('td')      :wikitext(link)                     :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(i.level)                  :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(xp))                 :attr('data-sort-value', xp)        :done()
                         :tag('td')      :wikitext(fnum(actionsRequired))    :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(membersOnly)              :css('text-align', 'center')        :done()
                         :done()
                    else -- Raising
                        -- Set bonus XP
                        local bonusXP   = getBonusXP(i, health, happiness, shiny, trait1, trait2, trait3)

                        -- Set variables & apply [Master] Farmer's Outfit bonus XP
                        local stage1xp  = math.ceil((bonusXP.stage1xp * pofoutfit) * 10) / 10
                        local stage2xp  = math.ceil((bonusXP.stage2xp * pofoutfit) * 10) / 10
                        local stage3xp  = math.ceil((bonusXP.stage3xp * pofoutfit) * 10) / 10
                        local stage4xp  = math.ceil((bonusXP.stage4xp * pofoutfit) * 10) / 10
                        local totalxp   = bonusXP.totalxp * pofoutfit
                        actionsRequired = math.ceil(remaining / totalxp)

                        r:tag('td')      :wikitext(icon)                                                         :done()
                         :tag('td')      :wikitext(link)                     :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(i.level)                  :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(stage1xp))           :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(stage2xp))           :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(stage3xp))           :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(stage4xp))           :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(fnum(totalxp))            :attr('data-sort-value', totalxp)   :done()
                         :tag('td')      :wikitext(fnum(actionsRequired))    :css('text-align', 'center')        :done()
                         :tag('td')      :wikitext(membersOnly)              :css('text-align', 'center')        :done()
                         :done()
                    end
                end
            end
        end
    end

    table.sort(t, function(a,b)
        return a > b
    end)

    -- Move to separate function once finished
    local cmsg = mw.html.create('div')
    if animals == 'Curing' then
        if not (head == 'Nenhum' and eyes == 'Nenhum' and legfeet == 'Nenhum' and stomach == 'Nenhum') then
            local cBone  = 0
            local cCurse = 0
            local cDry   = 0
            local cFlu   = 0
            local cFoot  = 0
            local cWoot  = 0

            local curse1, curse1pct

            -- Head
            if     head == 'O bafo deste animal tem um cheiro horrível' then                    cFlu   = cFlu + 1
            elseif head == 'Breath smells normal' then                               cBone  = cBone + 1
                                                                                     cWoot  = cWoot + 1
            elseif head == 'O bafo deste animal tem cheiro de meia suja' then                     cFoot  = cFoot + 1
            elseif head == 'Você não vê nada preocupante de imediato' then  		 cFoot  = cFoot + 1
                                                                                     cFlu   = cFlu + 1
                                                                                     cCurse = cCurse + 1
                                                                                     cBone  = cBone + 1
                                                                                     cWoot  = cWoot + 1
            elseif head == 'Coughs as you try and examine it' then                   cWoot  = cWoot + 1
            elseif head == 'O animal tosse na sua cara' then                                cFlu   = cFlu + 1
            elseif head == 'Coughs loudly in a `hu hu huuu` style' then              cWoot  = cWoot + 1
            elseif head == 'Há uma luz fraca vindo da garganta do animal' then        cCurse = cCurse + 1
            elseif head == 'As gengivas parecem estar doloridas' then                    cFoot  = cFoot + 1
            elseif head == 'Gums appear to be healthy' then                          cBone  = cBone + 1
            elseif head == 'O animal faz barulhos em momentos constrangedores, dificultando a investigação' then        cFoot  = cFoot + 1
            elseif head == 'Nasty looking marks along the gum line' then             cFoot  = cFoot + 1
            elseif head == 'Nose is lumpy' then                                      cCurse = cCurse + 1
            elseif head == 'O nariz do animal está muito seco' then                                   cDry   = cDry + 1
            elseif head == 'Nose seems fine' then                                    cBone  = cBone + 1
                                                                                     cWoot  = cWoot + 1
            elseif head == 'Occasionally mumbles' then                               cCurse = cCurse + 1
            elseif head == 'Refuses to let you see its nose' then                    cDry   = cDry + 1
            elseif head == 'O bafo deste animal tem um leve cheiro de enxofre' then                          cCurse = cCurse + 1
            elseif head == 'O animal espirra na sua cara' then                               cFlu   = cFlu + 1
            elseif head == 'Parece que o animal está com um pouco de febre' then                       cFlu   = cFlu + 1
            elseif head == 'Os dentes do animal rangem de um jeito sinistro' then                   cBone  = cBone + 1
            end

            -- Eyes
            if     eyes == 'Os olhos estão um pouco vermelhos' then                                 cFlu   = cFlu + 1
                                                                                     cCurse = cCurse + 1
                                                                                     cWoot  = cWoot + 1
            elseif eyes == 'Você não vê nada preocupante de imediato' then  		 cFoot  = cFoot + 1
                                                                                     cFlu   = cFlu + 1
                                                                                     cCurse = cCurse + 1
                                                                                     cDry   = cDry + 1
                                                                                     cBone  = cBone + 1
            elseif eyes == 'Os olhos do animal parecem normais' then                                   cFoot  = cFoot + 1
            elseif eyes == 'Os olhos do animal estão emitindo um brilho sutil' then                                    cCurse = cCurse + 1
            elseif eyes == 'Filled with mirth' then                                  cWoot  = cWoot + 1
            elseif eyes == 'Filled with uncharacteristic malice' then                cCurse = cCurse + 1
            elseif eyes == 'Keep darting around' then                                cWoot  = cWoot + 1
            elseif eyes == 'Seem a little glazed over' then                          cCurse = cCurse + 1
            elseif eyes == 'Os olhos do animal parecem bem' then                                          cDry   = cDry + 1
                                                                                     cBone  = cBone + 1
            end

            -- Legs & Feet
            if     legfeet == 'Os pés estão um pouco úmidos por algum motivo' then                  cFoot  = cFoot + 1
            elseif legfeet == 'A little unsteady on its feet' then                   cWoot  = cWoot + 1
            elseif legfeet == 'Are clammy' then                                      cFlu   = cFlu + 1
            elseif legfeet == 'Os pés do aminal estão levemente roídos' then                           cFoot  = cFoot + 1
                                                                                     cCurse = cCurse + 1
            elseif legfeet == 'Os pés do animal estão muito quentes ao toque' then                      cFlu   = cFlu + 1
            elseif legfeet == 'Are very sweaty' then                                 cFlu   = cFlu + 1
            elseif legfeet == 'Are tapping to a strange rhythm' then                 cCurse = cCurse + 1
            elseif legfeet == 'Você não vê nada preocupante de imediato' then		 cFoot  = cFoot + 1
                                                                                     cFlu   = cFlu + 1
                                                                                     cCurse = cCurse + 1
                                                                                     cDry   = cDry + 1
            elseif legfeet == 'Legs click as it walks' then                          cBone  = cBone + 1
            elseif legfeet == 'As pernas do animal parecem um pouco rígidas' then                        cBone  = cBone + 1
            elseif legfeet == 'Legs seem fine' then                                  cWoot  = cWoot + 1
            elseif legfeet == 'Os pés do animal parecem um pouco arranhados' then                           cFoot  = cFoot + 1
                                                                                     cCurse = cCurse + 1
            elseif legfeet == 'Seem fine' then                                       cFoot  = cFoot + 1
                                                                                     cFlu   = cFlu + 1
                                                                                     cCurse = cCurse + 1
                                                                                     cDry   = cDry + 1
            end

            -- Stomach
            if     stomach == 'O estômago parece um pouco inchado' then                  cFoot  = cFoot + 1
            elseif stomach == 'O animal parece estar tremendo, mas não tem febre' then                         cBone  = cBone + 1
            elseif stomach == 'Body is making a weird clicking noise' then           cBone  = cBone + 1
            elseif stomach == 'Body is slightly swollen' then                        cWoot  = cWoot + 1
            elseif stomach == 'Você não vê nada preocupante de imediato' then		 cFoot  = cFoot + 1
                                                                                     cFlu   = cFlu + 1
                                                                                     cCurse = cCurse + 1
                                                                                     cDry   = cDry + 1
                                                                                     cBone  = cBone + 1
                                                                                     cWoot  = cWoot + 1
            elseif stomach == 'Coughs regularly' then                                cWoot  = cWoot + 1
            elseif stomach == 'O animal não parece estar com dores gastrointestinais' then    cFoot  = cFoot + 1
                                                                                     cFlu   = cFlu + 1
                                                                                     cCurse = cCurse + 1
                                                                                     cDry   = cDry + 1
                                                                                     cBone  = cBone + 1
                                                                                     cWoot  = cWoot + 1
            elseif stomach == 'As emissões do animal têm um cheiro parecido com o de sapatos' then              cFoot  = cFoot + 1
            elseif stomach == 'O animal tem um pouco de gases, mas nada muito preocupante' then                                cFoot  = cFoot + 1
                                                                                     cFlu   = cFlu + 1
                                                                                     cCurse = cCurse + 1
                                                                                     cDry   = cDry + 1
                                                                                     cBone  = cBone + 1
                                                                                     cWoot  = cWoot + 1
            elseif stomach == 'Making strange noises' then                           cCurse = cCurse + 1
            elseif stomach == 'O animal parece estranhar sua comida' then                                    cFlu   = cFlu + 1
                                                                                     cCurse = cCurse + 1
            elseif stomach == 'Suffering from nausea' then                           cFlu   = cFlu + 1
            end

            local curseArray = {cBone, cCurse, cDry, cFlu, cFoot, cWoot}
            table.sort(curseArray, function(a,b)
                return a > b
            end)

            local curseList = ''
            for i, v in ipairs(curseArray) do
                curseList = curseList .. v .. '<br>'
            end

            -- Easier way to do this?
            -- Currently does not take into effect possible "ties"
            -- Also display the probability of the other curses, sorted?
            --[=[
            --]=]
            if cBone > cCurse then
                if cBone > cDry then
                    if cBone > cFlu then
                        if cBone > cFoot then
                            if cBone > cWoot then   curse1pct = math.floor((cBone / 6) * 100)
                                                    curse1 = 'Bone Rattle'
                            else                    curse1pct = math.floor((cWoot / 6) * 100)
                                                    curse1 = 'Tosse Confusa' end
                        else                        curse1pct = math.floor((cFoot / 6) * 100)
                                                    curse1 = 'Foot-in-Mouth' end
                    else                            curse1pct = math.floor((cFlu / 6) * 100)
                                                    curse1 = 'Gripe' end
                else                                curse1pct = math.floor((cDry / 6) * 100)
                                                    curse1 = 'Nariz seco' end
            else                                    curse1pct = math.floor((cCurse / 6) * 100)
                                                    curse1 = 'Maldição'
            end

            local cmsgtxt = 'The most likely illness is the '..curse1..' at '..curse1pct..'%.'
            cmsg:tag('p'):css({['font-size'] = "1.1em", ['font-weight'] = "bold"}):wikitext(cmsgtxt):done()
        end
    end

    local msg = mw.html.create('div')

    -- Add message of xp needed to reach target
    if has_target then
        local msgtxt = 'To train Farming from '..fnum(farm_xp)..' experience (level '..farm_level..') to '..fnum(target_xp)..' experience (level '..target_lvl..'), '..fnum(remaining)..' experience is required.'
        msg:tag('p'):css({['font-size'] = "1.1em", ['font-weight'] = "bold"}):wikitext(msgtxt):done()
    end

    return tostring(cmsg)..tostring(msg)..tostring(t)
end

--[=[ getMats
-- Calculates and returns the required materials and their cost
-- Inputs:
--      i             Data from Module:Farm Data (material, payment, master, trade, mtrade)
--      amount        Total number of items made
--      plots         Selected plot type from the calculator
--      outfit        Number of Master Outfit pieces worn
--      payment_show  Include or exclude the payment cost
-- Returns:
--      Wikitext string of materials, the number needed and the price.
--]=]
function getMats(i, amount, plots, patch, outfitpcs, payment_show, regrown)
    local ret         = ''
    local matnum      = amount          -- Actions required (for material calculations)
    local pmtnum      = amount          -- Actions required (for payment calculations)
    local pymnt       = ''
    local cost        = 0               -- Total cost of the seeds
    local count       = 0               -- 
    local paymentCost = 0               -- Cost of payment product
    local productCost = 0               -- Cost of the final product (i.name * #)
    local profit      = 0               -- Profit/loss (productCost - (cost + paymentCost))
    local rawCost     = 0               -- Cost of one seed
    local name        = i.name
    local mats        = i.material
    local payment     = i.payment
    local master      = i.master
    local trade       = i.trade
    local mtrade      = i.mtrade
    local ptrade      = i.ptrade
    local currency    = 'coins'

    if i.currency then
        currency = i.currency
        rawCost  = i.mCost
    end

    if amount == 0 or mats == nil then
        return {display = '-', payment = '-', rawCost = '-', cost = '-', count = 0, profit = '-'}
    elseif (plots == 'Arbustos' and regrown == 'Sim') or ((patch == 'Cristal' or patch == 'Fruta') and regrown == 'Sim') then
        matnum = 1
        pmtnum = 1
    end

    if mats then
        for _, mat in ipairs(mats) do
            if type(mat) == "number" then
                matnum = matnum * mat
            end

            ret     = '[[Arquivo:' .. mat .. '.png|link=' .. mat .. ']] ' .. fnum(matnum) .. '<br>'

            if mtrade ~= 0 then
                if type(mat) == "string" then
                    rawCost = getCost(mat)
                end
                cost        = rawCost * matnum
                if trade ~= 0 then
                    productCost = getCost(name) * matnum
                end
            elseif currency ~= 'moedas' then
                cost        = rawCost * matnum
            end
            count   = amount
        end
    end

    if payment then
        for _, pmt in ipairs(payment) do
            if type(pmt) == "number" then
                -- Subtract 1 or 2 items from certain payments if full Master Outfit is worn
                if outfitpcs == '5 Partes' then
                    if pmt > 1 then -- Exclude items that are only required once (see Spirit tree)
                        if     master == 0 then pmt = pmt - 2
                        elseif master == 1 then pmt = pmt - 1 end
                    end
                end
                pmtnum = pmtnum * pmt
            end

            if type(pmt) == "string" then
                pymnt     = pymnt .. '[[Arquivo:' .. pmt .. '.png|link=' .. pmt .. ']] ' .. fnum(pmtnum) .. '<br>'
                if ptrade ~= 0 and payment_show == 'Sim' then
                    paymentCost = getCost(pmt) * pmtnum
                end
            end
        end
        profit = coins((productCost - (cost + paymentCost)), currency)
    else
        pymnt  = '-'
        profit = coins((productCost - cost), currency)
    end

    return {display = ret, payment = pymnt, rawCost = coins(rawCost, currency), cost = coins(cost, currency), count = count, profit = profit}
end

function getCost(item)
    return gemw.price(item)
end

-- POF/RoOT bonuses
function getBonusXP(i, health, happiness, shiny, trait1, trait2, trait3)
    local stage1xp = i.stage1
    local stage2xp = i.stage2
    local stage3xp = i.stage3
    local stage4xp = i.stage4
    local totalxp  = i.xp
    local newxp    = 10

    -- Set base XP for all stages based on health & happiness
    if health ~= nil and happiness ~= nil then
        newxp    = math.ceil((health + happiness) / 2)
        if newxp < 10 then newxp = 10 end -- cannot be below 10
        stage1xp = ((stage1xp * newxp) / 100)
        stage2xp = ((stage2xp * newxp) / 100)
        stage3xp = ((stage3xp * newxp) / 100)
        stage4xp = ((stage4xp * newxp) / 100)
        totalxp  = ((totalxp * newxp) / 100)
    end

    -- Apply the Shiny bonus to each stage
    if shiny == 1.1 then
        stage1xp = stage1xp * shiny
        stage2xp = stage2xp * shiny
        stage3xp = stage3xp * shiny
        stage4xp = stage4xp * shiny
        totalxp  = totalxp * shiny
    end

    -- Apply trait bonuses
    if trait1 == "Giver" then           stage1xp = stage1xp * 1.03
                                        stage2xp = stage2xp * 1.03
                                        stage3xp = stage3xp * 1.03
                                        stage4xp = stage4xp * 1.03
                                        totalxp  = totalxp * 1.03 end
    if trait2 == "Giver" then           stage1xp = stage1xp * 1.03
                                        stage2xp = stage2xp * 1.03
                                        stage3xp = stage3xp * 1.03
                                        stage4xp = stage4xp * 1.03
                                        totalxp  = totalxp * 1.03 end
    if trait3 == "Giver" then           stage1xp = stage1xp * 1.03
                                        stage2xp = stage2xp * 1.03
                                        stage3xp = stage3xp * 1.03
                                        stage4xp = stage4xp * 1.03
                                        totalxp  = totalxp * 1.03 end

    if trait1 == "Limited Efficiency" 
        or trait1 == "Taker" then       stage1xp = stage1xp - (stage1xp * 0.03)
                                        stage2xp = stage2xp - (stage2xp * 0.03)
                                        stage3xp = stage3xp - (stage3xp * 0.03)
                                        stage4xp = stage4xp - (stage4xp * 0.03)
                                        totalxp  = totalxp - (totalxp * 0.03) end
    if trait2 == "Limited Efficiency" 
        or trait2 == "Taker" then       stage1xp = stage1xp - (stage1xp * 0.03)
                                        stage2xp = stage2xp - (stage2xp * 0.03)
                                        stage3xp = stage3xp - (stage3xp * 0.03)
                                        stage4xp = stage4xp - (stage4xp * 0.03)
                                        totalxp  = totalxp - (totalxp * 0.03) end
    if trait3 == "Limited Efficiency"
       or trait3 == "Taker" then        stage1xp = stage1xp - (stage1xp * 0.03)
                                        stage2xp = stage2xp - (stage2xp * 0.03)
                                        stage3xp = stage3xp - (stage3xp * 0.03)
                                        stage4xp = stage4xp - (stage4xp * 0.03)
                                        totalxp  = totalxp - (totalxp * 0.03) end

    if trait3 == "Exalted" then         stage1xp = stage1xp * 1.03
                                        stage2xp = stage2xp * 1.03
                                        stage3xp = stage3xp * 1.03
                                        stage4xp = stage4xp * 1.03
                                        totalxp  = totalxp * 1.03 end
    if trait3 == "Nice but Dim" then    stage1xp = stage1xp * 1.144
                                        stage2xp = stage2xp * 1.144
                                        stage3xp = stage3xp * 1.144
                                        stage4xp = stage4xp * 1.144
                                        totalxp  = totalxp * 1.144 end

    --[=[
    -- Requires bonus XP %
    if trait3 == "Freak of Nature" then stage1xp = stage1xp * [x]
                                        stage2xp = stage2xp * [x]
                                        stage3xp = stage3xp * [x]
                                        stage4xp = stage4xp * [x]
                                        totalxp  = totalxp * [x] end
    --]=]
    return {stage1xp = stage1xp, stage2xp = stage2xp, stage3xp = stage3xp, stage4xp = stage4xp, totalxp = totalxp}
end

function outfitBonus(outfit, xp)
    --if     outfit == "1 Piece"  then    xp = xp * 1.01
    --elseif outfit == "2 Pieces" then    xp = xp * 1.02
    --elseif outfit == "3 Pieces" then    xp = xp * 1.03
    --elseif outfit == "4 Pieces" then    xp = xp * 1.04
    --elseif outfit == "5 Pieces" then    xp = xp * 1.06 end
    if not outfit then outfit = 1 end

    xp = math.ceil(xp * 10) / 10

    return xp
end

--[=[ trimArray
-- Trims an array to a given length
-- Inputs:
--      array        The array to be trimmed
-- Returns:
--      The array trimmed to a length of 50
--]=]
function trimArray(array)
    local len = table.getn(array)
    if len > 50 then
        for i=len, 50, -1 do
            array[i] = nil
        end
    end
    return array
end

--[=[ remainingExp
-- Finds and returns experiences and levels based on inputs
-- Inputs:
--      curLvl        The current level or 1
--      curXP         The current xp or 1
--      tgtLvl        The target level or 0
--      tgtXP         The target xp or 0
-- Returns:
--      current level,
--      current experience,
--      goal level,
--      goal experience,
--      experience remaining
--]=]
function remainingExp(curLvl, curXP, tgtLvl, tgtXP)
    local remaining

    if curLvl > 120 and curXP == 1 then
        curXP = curLvl
    elseif curXP <= 120 and curLvl == 1 then
        curLvl = curXP
        curXP = 1
    end
    if tgtLvl > 120 and tgtXP == 0 then
        tgtXP = tgtLvl
    elseif tgtXP <= 120 and tgtLvl == 0 then
        tgtLvl = tgtXP
        tgtXP = 0
    end

    if curXP == 1 then
        curXP = xp({args = {curLvl, elite = 0}})
    else
        curLvl = level({args = {curXP, elite = 0}})
    end

    if tgtLvl > 0 or tgtXP > 0 then
        if tgtXP == 0 then
            tgtXP = xp({args = {tgtLvl, elite = 0}})
        else
            tgtLvl = level({args = {tgtXP, elite = 0}})
        end
    end
    
    -- Prevent negative values
    local remaining = math.ceil(tgtXP - curXP)
    if remaining < 0 then
        remaining = 0
    end
    return curLvl, curXP, tgtLvl, tgtXP, remaining
end

function fnum(x)
    if type(x) == 'number' then
        return lang:formatNum( x )
    end
    return x
end

return p