Module:Tree cost calculator

From WIDEVERSE Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Tree cost calculator/doc

local data = mw.loadData('Module:Tree cost calculator/data')
local prices = mw.loadData('Module:GEPrices/data')
local yn = require('Module:Yesno')
local lang = mw.getContentLanguage()
local p = {}
local bonuses = {}

function p.main(frame)
    return p._main(frame:getParent().args)
end

local function error_text(text)
    return string.format("<span class='error'>%s</span>", text)
end

local function create_builder()
    return { results = {}, i = 1 }
end

local function create_results_builder()
    return {
        base_experience = create_builder(),
        bonus_experience = create_builder(),
        cost = create_builder(),
        savings = create_builder()
    }
end

local function add_line(result_builder, text)
    result_builder.results[result_builder.i] = text
    result_builder.i = result_builder.i + 1
end

local function add_base_experience_line(results, line)
    add_line(results.base_experience, line)
end

local function add_bonus_experience_line(results, line)
    add_line(results.bonus_experience, line)
end

local function add_cost_line(results, line)
    add_line(results.cost, line)
end

local function add_savings_line(results, line)
    add_line(results.savings, line)
end

local function format_number(number)
    return lang:formatNum(math.floor(number * 100) / 100)
end

local function link_to(name)
    return string.format("[[%s]]", name)
end

function bonuses.premier_artifact(results, used)
    if used then
        add_bonus_experience_line(results, "* Premier artifact: +10%")
        return 0.1
    end
    return 0
end

function bonuses.wisdom_aura(results, used)
    if used then
        add_bonus_experience_line(results, "* Wisdom aura: +2.5%")
        return 0.025
    end
    return 0
end

function bonuses.brassica_primer(results, used)
    if used then
        add_bonus_experience_line(results, "* Brassica primer: +10%")
        return 0.1
    end
    return 0
end

function bonuses.farming_outfit(results, count)
    if count == 5 then
        add_bonus_experience_line(results, "* Farming outfit: +6%")
        return 0.06
    end
    if count ~= 0 then
        add_bonus_experience_line(results, "* Farming outfit: +" .. tostring(count) .. "%")
    end
    return count * 0.01
end

function bonuses.pulse_core_worn(results, worn)
    if worn then
        add_bonus_experience_line(results, "* Advanced pulse core (worn): +50%")
        return 0.5
    end
    return 0
end

function bonuses.wise_perk(results, level)
    if level ~= 0 then
        add_bonus_experience_line(results, "* Wise perk: +" .. tostring(level) .. "%")
    end
    return level * 0.01
end

function bonuses.pulse_core_bonus(results, percent)
    if percent ~= 0 then
        add_bonus_experience_line(results, "* Advanced pulse core bonus: +" .. tostring(percent) .. "%")
    end
    return percent * 0.01
end

function bonuses.avatar_habitat(results, percent)
    if percent ~= 0 then
        add_bonus_experience_line(results, "* Clan avatar bonus: +" .. tostring(percent) .. "%")
    end
    return percent * 0.01
end

function bonuses.bonus_xp(results, used)
    if used then
        add_bonus_experience_line(results, "* Bonus experience: +100%")
        return 1
    end
    return 0
end

function bonuses.double_xp(results, used)
    if used then
        add_bonus_experience_line(results, "* Double experience week/weekend: +100%")
        return 1
    end
    return 0
end

function bonuses.farming_urn(results, used, enhancer)
    if used then
        local bonus = 0.2
        add_bonus_experience_line(results, "* Farming urn: +20%")
        if enhancer then
            bonus = bonus + 0.05
            add_bonus_experience_line(results, "* Urn enhancer: +5%")
        end
        return bonus
    end
    return 0
end

function p._main(args)
    -- TODO Cinder core (worn and effect) ?

    local tree_name = args.tree_name
    local experience_data = data.experience[tree_name]
    if not experience_data then return "" end
    
    local results = create_results_builder();
    
    local master_farmer_outfit = yn(args.master_farmer_outfit)
    local farming_urn = args.farming_urn
    local urn_enhancer = yn(args.urn_enhancer)
    local pay_to_protect = yn(args.pay_to_protect)
    local sell_harvests = yn(args.sell_harvests)
    local giant_ent = yn(args.giant_ent)
    local scroll_of_life = yn(args.scroll_of_life)
    local manual_seed_cost = tonumber(args.manual_seed_cost)
    local manual_harvest_cost = tonumber(args.manual_harvest_cost)
    
    local base_experience = experience_data.plant + experience_data.check
    add_base_experience_line(results, "Base experience:")
    add_base_experience_line(results, string.format("* Planting: %s", format_number(experience_data.plant)))
    add_base_experience_line(results, string.format("* Checking: %s", format_number(experience_data.check)))
    
    local harvestable = experience_data.harvest or false
    if harvestable then
        base_experience = base_experience + (experience_data.harvest * experience_data.harvests)
        add_base_experience_line(results, string.format("* Harvesting: %s x %s",
                                                        format_number(experience_data.harvest),
                                                        tostring(experience_data.harvests)))
    end
    
    add_base_experience_line(results, string.format("* Total: %s", format_number(base_experience)))
    
    local premier_artifact = yn(args.premier_artifact)
    local wisdom_aura = yn(args.wisdom_aura)
    
    add_bonus_experience_line(results, "Bonus experience:")
    local bonus = bonuses.avatar_habitat(results, tonumber(args.avatar_habitat)) +
                  bonuses.wise_perk(results, tonumber(args.wise_perk)) +
                  bonuses.pulse_core_bonus(results, tonumber(args.pulse_core_bonus)) +
                  bonuses.brassica_primer(results, yn(args.brassica_primer)) +
                  bonuses.premier_artifact(results, premier_artifact) +
                  bonuses.wisdom_aura(results, wisdom_aura) +
                  bonuses.farming_outfit(results, tonumber(args.farming_outfit)) +
                  bonuses.pulse_core_worn(results, yn(args.pulse_core_worn)) +
                  bonuses.bonus_xp(results, yn(args.bonus_xp)) +
                  bonuses.double_xp(results, yn(args.double_xp))
    
    local urns_used = 0
    if farming_urn and farming_urn ~= 'None' then
        local urn_data = data.urns[farming_urn]
        
        -- Reject; urns don't work for this seed level
        if urn_data.max_level < data.levels[tree_name] then
            return error_text(string.format("%s urns only works on plants up to level %s. %s is level %s.",
                                            farming_urn,
                                            tostring(urn_data.max_level),
                                            tree_name,
                                            tostring(data.levels[tree_name])))
        end
        
        bonus = bonus + bonuses.farming_urn(results, farming_urn, urn_enhancer)
        urns_used = base_experience / urn_data.base
    end
    
    local total_experience = base_experience + (base_experience * bonus)
    
    if bonus ~= 0 then
        add_bonus_experience_line(results, string.format("* Total: %s%%", tostring(bonus * 100)))
        
        add_bonus_experience_line(results, "\nFinal experience:")
        local bonus_string = tostring(1 + bonus)
        add_bonus_experience_line(results, string.format("* Planting: %s x %s: %s",
                                                         format_number(experience_data.plant),
                                                         bonus_string,
                                                         format_number(experience_data.plant * (1 + bonus))))
        add_bonus_experience_line(results, string.format("* Checking: %s x %s: %s",
                                                         format_number(experience_data.check),
                                                         bonus_string,
                                                         format_number(experience_data.check * (1 + bonus))))
        
        if harvestable then
            add_bonus_experience_line(results, string.format("* Harvesting: %s x %s x %s: %s",
                                                             tostring(experience_data.harvest),
                                                             tostring(experience_data.harvests),
                                                             bonus_string,
                                                             format_number(experience_data.harvest * experience_data.harvests * (1 + bonus))))
        end
        
        add_bonus_experience_line(results, string.format("* Total: %s x %s: %s",
                                                         format_number(base_experience),
                                                         bonus_string,
                                                         format_number(total_experience)))
    end
    
    --[[ BASE COST CALCULATION ]]--
    local base_cost = 0
    add_cost_line(results, "\nCosts:")
    
    -- Seed cost
    local seed_cost = prices[tree_name]
    if manual_seed_cost and manual_seed_cost ~= 0 then
        seed_cost = manual_seed_cost
    end
    add_cost_line(results, string.format("* %s: %s", link_to(tree_name), format_number(seed_cost)))
    base_cost = base_cost + seed_cost
    
    -- Farming urn cost
    if farming_urn and farming_urn ~= 'None' then
        local urn_cost = prices[data.urns[farming_urn].name]
        local nature_rune_cost = prices['Nature rune']
        
        base_cost = base_cost + ((urn_cost + nature_rune_cost) * urns_used)
        add_cost_line(results, string.format("* %g urns: %s", urns_used, format_number(urn_cost * urns_used)))
        add_cost_line(results, string.format("* %g nature runes: %s", urns_used, format_number(nature_rune_cost * urns_used)))
        
        if urn_enhancer then
            local divine_charge_cost = prices['Divine charge']
            local added_cost = (divine_charge_cost / 150) * urns_used
            base_cost = base_cost + added_cost
            add_cost_line(results, string.format("* %g divine charge (urn enhancer): %s",
                                                 added_cost / divine_charge_cost,
                                                 format_number(added_cost)))
        end
    end
    
    -- Payment costs
    if pay_to_protect then
        local payment_data = data.payments[tree_name]
        local single_cost = prices[payment_data.name]
        local payment_count = payment_data.count
        local master_farmer_discount = ""
        if master_farmer_outfit then
            payment_count = math.max(1, payment_count - 2)
            master_farmer_discount = " (-2 master farmer outfit)"
        end
        add_cost_line(results, string.format("* %s%s %s: %s",
                                             tostring(payment_count),
                                             master_farmer_discount,
                                             link_to(payment_data.name),
                                             format_number(single_cost * payment_count)))
        
        base_cost = base_cost + (single_cost * payment_count)
    end
    add_cost_line(results, string.format("* Total: %s", format_number(base_cost)))
    
    
    --[[ PROJECTED SAVINGS ]]--
    local savings = 0
    add_savings_line(results, "\nAverage savings:")
    
    -- Selling harvests
    if sell_harvests and harvestable then
        local harvest_data = data.harvests[tree_name]
        local harvest_count = harvest_data.count
        
        local single_cost = prices[harvest_data.name]
        if manual_harvest_cost and manual_harvest_cost ~= 0 then
            single_cost = manual_harvest_cost
        end
        add_savings_line(results, string.format("* %s %s: %s",
                                                harvest_count,
                                                link_to(harvest_data.name),
                                                format_number(harvest_data.count * single_cost)))
        
        if giant_ent then
            local ent_chances = experience_data.harvests
            harvest_count = harvest_count + (ent_chances * 0.5)
            add_savings_line(results, string.format("* %g %s (giant ent): %s",
                                                    ent_chances * 0.5,
                                                    link_to(harvest_data.name),
                                                    format_number((ent_chances * 0.5) * single_cost)))
        end
        
        if master_farmer_outfit then
            local outfit_chances = experience_data.harvests
            harvest_count = harvest_count + (outfit_chances * 0.1)
            add_savings_line(results, string.format("* %g %s (master farmer outfit): %s",
                                                    outfit_chances * 0.1,
                                                    link_to(harvest_data.name),
                                                    format_number((outfit_chances * 0.1) * single_cost)))
        end
        
        savings = savings + (harvest_count * single_cost)
    end
    
    -- Saving a seed
    if scroll_of_life then
        local seed_savings = (seed_cost * 0.1);
        savings = savings + seed_savings
        add_savings_line(results, string.format("* 0.1 %s (scroll of life): %s",
                                                link_to(tree_name),
                                                format_number(seed_savings)))
    end
    if savings ~= 0 then
        add_savings_line(results, string.format("* Total: %s", format_number(savings)))
    end
    
    local builder = create_builder()
    
    -- GP per XP
    add_line(builder, "Gold pieces per experience:")
    add_line(builder, string.format("* (%s - %s)/%s = %s GP/XP",
                                    format_number(base_cost),
                                    format_number(savings),
                                    format_number(total_experience),
                                    format_number((base_cost - savings) / total_experience)))
    add_line(builder, "")
    
    for _,v in ipairs(results.base_experience.results) do
        add_line(builder, v)
    end
    
    if bonus ~= 0 then
        for _,v in ipairs(results.bonus_experience.results) do
            add_line(builder, v)
        end
    end
    
    for _,v in ipairs(results.cost.results) do
        add_line(builder, v)
    end
    
    if savings ~= 0 then
        for _,v in ipairs(results.savings.results) do
            add_line(builder, v)
        end
    end
    
    add_line(builder, "\nNotes:")
    add_line(builder, "* Assumes continual replanting")
    
    if sell_harvests and not harvestable then
        add_line(builder, "* Tree has no harvests")
    end
    
    if giant_ent then
        if sell_harvests and harvestable then
            add_line(builder, "* Giant ent pouch cost is not included")
        elseif not sell_harvests then
            add_line(builder, "* Giant ent has no effect because the harvests aren't being sold")
        elseif sell_harvests and not harvestable then
            add_line(builder, "* Giant ent has no effect because the tree has no harvests")
        end
    end
    
    return table.concat(builder.results, '\n')
end

function p.tree_list()
    local l = {}
    for k,v in pairs(data.names) do
        table.insert(l, v)
    end
    table.sort(l)
    return table.concat(l, ',')
end

function p.urn_list()
    local l = {}
    for k,v in pairs(data.urns) do
        l[v.order] = k
    end
    return table.concat(l, ',')
end

return p