Module:Sandbox/User:F0r F0x Sake/calctest

From WIDEVERSE Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Sandbox/User:F0r F0x Sake/calctest/doc

--- this is a comment - from a -- to the end of a line
-- whatever is in a comment does nothing
--[=[
    this is a block comment, from --[(any number of =)[ to ](the same number of =)]
    you can use 0 but that isn't encouraged as it can be confused with wikilinks
    
    the -- when closing isn't required but it does make it line up nicely
--]=]

-- <nowiki>
-- a commented nowiki does nothing to the code but ensures there is no false whatlinkshere

--[======[
    STEP 1
    declare a main variable and define it as an empty table
    see also - step 3 at the end
--]======]
-- conventionally this is named p
local p = {}

--[==[
helper functions
these are up here as they generally need to be reasonably high up
--]==]
-- helper function that just gets GE prices
-- load in GE prices
-- loadData works slightly differently to require - if the relevant conditions are fulfilled, loadData should be used instead of require
local geps = mw.loadData('Module:GEPrices/data')
-- fetch the GE price out of the table or return 0 if it doesn't exist
function gep(item)
    return geps[item] or 0
end



local curr = require('Module:Currency')._amount
-- a helper function to make coins images
function coins(x)
    return curr(string.format('%.2f',x), 'coins')
end
-- a helper function to make coins images
local yesno = require('Module:Yesno')
-- not sure if yesno goes here in this format. Check here first if any issues arise.
local scrollInfo = {
    [true] = .9,
    [false] = 1
}    
local maskInfo = {
    [true] = .05,
    [false] = 0
}    
local portableInfo = {
    [true] = .05,
    [false] = 0
}    
local broochInfo = {
    [true] = .05,
    [false] = 0
}    
local amuletInfo = {
    [true] = .05,
    [false] = 0    
}    
local factoryInfo = {
    [true] = .1,
    [false] = 0   
}    
local desertInfo = {
    [true] = .2,
    [false] = 0    
}    
local morytaniaInfo = {
    [true] = .2,
    [false] = 0
}    
local varanusaurInfo = {
    [true] = .1,
    [false] = 0
}

--[======[
    STEP 2
    assign functions into p
--]======]
-- `main` is a common name for the function that wikitext will call
-- the only passed input for the function called by wikitext is a Frame, often just called frame
function p.main(frame)
    -- it is common to strip out the arguments from the frame, then pass those into another function
    -- this is because we can then test the module in the console or without a tegamplate
    -- getParent() will error if there is no parent, which is the case in the console or without a template
    return p._main(frame:getParent().args)
end

-- this function is also part of p but can be called with just the arguments, i.e. in the console
function p._main(args)
    -- local is the keyword to declare a variable in the current scope

    local scroll, portable, brooch, factory, desert, morytania, varanusaur, mask, amulet  = args.Scroll_Input, args.Portable_Input, args.Brooch_Input, args.Factory_Input, args.Desert_Input, args.Morytania_Input, args.Varanusaur_Input, args.Mask_Input, args.Amulet_Input
    
    --declares and assigns the variables
 
    scroll = yesno(scroll or '', false)
    
    mask = yesno(mask or '', false)
    
    portable = yesno(portable or '', false)
    
    brooch = yesno(brooch or '', false)
    
    amulet = yesno(amulet or '', false)
    
    factory = yesno(factory or '', false)
    
    desert = yesno(desert or '', false)
    
    morytania = yesno(morytania or '', false)

    varanusaur = yesno(varanusaur or '', false)
    --uses yesno because these are checkboxes.
    
	--building table here
    local ret = makeTable(scroll, portable, brooch, factory, desert, morytania, varanusaur, mask, amulet)

    -- make sure to return the relevant thing at the end
    return ret
end


--[=[
    data tables
--]=]
-- before moving on to the function, we're going to setup some data tables
-- again, this is usually at the top, between step 1 and 2
-- but for demonstration they're here

-- these data tables are for mapping from the values passed from the frame into the actual values we care about





-- this is the main data table containing all the information about the herbs
-- the outer table is using another alternative notation, providing no keys at all
-- this makes it behave like a standard array in other langs - the keys will begin at 1 (the number 1 not the string '1' - these are different keys!) and increment by 1 for each un-keyed item in it
local potionInfo = {
    {
        name = 'Attack potion', -- potion name
        level = 1, -- herblore level level
        experience = 25, --xp
        herb = 'Guam', -- herb name
        primary = '', --fill if potion uses a non-standard primary
        secondary = 'Eye of newt', -- secondary ingredient
       
    },
    {
        name = 'Ranging potion', -- potion name
        level = 3, -- herblore level level
        experience = 30, --xp
        herb = 'Guam', -- herb name
        primary = '', --fill if potion uses a non-standard primary
        secondary = 'Redberries', -- secondary ingredient
       
    },
    
    -- fill in with more potions
}



function makeTable(scroll, mask, portable, brooch, amulet, factory, desert, morytania, varanusaur)
    -- declare t as a mw.html object
    -- mw.html is used to make html tag creation generally easier
    local t = mw.html.create('table')

    -- this is a method of the mw.html object
    -- this is actually syntactic sugar for mw.html.addClass(t, 'wikitable'), but using that is dumb if you don't have to
    t:addClass('wikitable')
    
    -- add more classes
    -- I like to have numbers aligned right except for levels, which are aligned center
    -- since only 3 columns aren't aligned right, use style to align right then override with classes
    t:css('text-align', 'right')
    t:addClass('align-left-1 align-center-2 align-center-3 ')

    -- you can chain this syntax, if the object returns a value that is an object (which all of mw.html does)
    -- whitespace doesn't matter so it is good to indent to make the structure clear
    t:tag('tr') -- create a table row (tr)
    	:tag('th') -- create a table header cell (th)
            :wikitext('Icon') -- add some content to the th
        :done() 
        :tag('th') 
            :wikitext('Potion') 
        :done() 
        :tag('th') 
            :wikitext('[[File:Herblore.png|20px|frameless|link=Herblore]] level') 
        :done()
        :tag('th') 
            :wikitext('XP') 
        :done()         
        :tag('th')
            :wikitext('&nbsp;')
            :addClass('unsortable')
            :attr('rowspan', #potionInfo+1) -- make this as long as the potionInfo table, plus 1 for the header
        :done()        
        :tag('th')
            :wikitext('Primary')
        :done()
        :tag('th')
            :wikitext('Primary cost')
        :done()
        :tag('th')
            :wikitext('&nbsp;')
            :addClass('unsortable')
            :attr('rowspan', #potionInfo+1) -- make this as long as the potionInfo table, plus 1 for the header
        :done()        
        :tag('th')
            :wikitext('Secondary')
        :done()
        :tag('th')
            :wikitext('Secondary cost')
        :done()
        :tag('th')
            :wikitext('&nbsp;')
            :addClass('unsortable')
            :attr('rowspan', #potionInfo+1) -- make this as long as the potionInfo table, plus 1 for the header
        :done()
        :tag('th')
        -- we're not going to put the references here for now, since they are complicated
        -- if you are interested I can add them later
            :wikitext('Profit')
        :done()
        :tag('th')
            :wikitext('GP/XP')
        :done()

:done()

    -- header is now done!
    -- we can call :done() or :addDone() here but it isn't necessary since we are now done chaining, starting a new statement wil work just fine

    -- now we're going to iterate the entire herbs table
    -- but before that, there are a few things we'll be using over the entire iteration, so setup a few variables
    -- get the compost number from the info, default to none if an invalid value was provided
    -- for the calculator you shouldn't ever have an invalid value, but it is good practice to check anyway (unless you intentionally want it to script error)
	local maskVal = maskInfo[mask] or 1
	local factoryVal = factoryInfo[factory] or 1
	local portableVal = portableInfo[portable] or 1
	local amuletVal = amuletInfo[amulet] or 1
	local varanusaurVal = varanusaurInfo[varanusaur] or 1
	local desertVal = desertInfo[desert] or 1
	local morytaniaVal = morytaniaInfo[morytania] or 1
	local scrollVal = scrollInfo[scroll] or 1
	local broochVal = broochInfo[brooch] or 1
    -- since these are always just added together anyway
    local doubleMultiplier = 1 + broochVal + maskVal + portableVal or 1
    local doseMultiplier = 1 + factoryVal + amuletVal or 1
    local standardMultiplier = doubleMultiplier * doseMultiplier or 1
    local poisondoseMultiplier = 1 + factoryVal + amuletVal + varanusaurVal or 1
    local poisonMultiplier = poisondoseMultiplier * doubleMultiplier or 1
    local morytaniadoseMultiplier = 1 + factoryVal + amuletVal + morytaniaVal or 1
    local desertdoseMultiplier = 1 + factoryVal + amuletVal + desertVal or 1
    local morytaniaMultiplier = morytaniadoseMultiplier * doubleMultiplier or 1
    local desertMultiplier = desertdoseMultiplier * doubleMultiplier     or 1

    -- ok now we can begin the iteration
    -- this uses a common form of the for statement
    -- you can read this as "declare the variables i and v; for every item in the herbsInfo table in order, assign the key to i and the value to v, then execute the code inside"
    -- if that doesn't make sense, don't worry - if you've never encountered loops before, they can be a brainbender
    for i,v in ipairs(potionInfo) do

        -- create a tr inside the return table, and store it
        local tr = t:tag('tr')
        
        -- there's a number of things happening right here
        -- 1) get the herbname from the current herb table we're looking at, and use that if it exists
        -- 2) if herbname doesn't exist it will be nil and thus we trigger the other side of the or
        -- 3) we take the string 'Grimy ' (with a space) and concatenate it (the .. operator) to
        -- 4) the name from the current herb table, lowercased - if we know that the variable is a string, we can do the : syntactic sugar like on mw.html objects (this is equivalent to string.lower(v.name))
        local potion = v.name

        -- we'll use these a few times, so lets set up some variables for prices
        -- seed price: 2 steps of overrides - an explicit seedprice
        --      if not set, find the gep of the seed name
        --      if not set, find the gep of the herb name + seed
        local herbprice = v.herbprice or gep('Clean '..v.herb)
        local primaryprice = v.primaryprice or gep(v.primary)
        -- can add fixed primary price if that applies to a given potion.
        local potionprice = v.potionprice or gep(v.potion)
        local secondaryprice = v.secondaryprice or gep(v.secondary)

        -- calculate the various values
        -- just define these important variables here, fill in later - these go into the table


         local scrollsecondaryprice, totalprice, moddedvalue, profit, gpxp
        scrollsecondaryprice = secondaryprice * scrollVal
        totalprice = herbprice + scrollsecondaryprice
        moddedvalue = potionprice * standardMultiplier
        -- need to add here the conditions for the desert/mory/poison stuff.
        profit = moddedvalue - totalprice
        gpxp = profit / v.experience
        


        
        tr  :tag('td') -- td tag is a normal cell
                :wikitext(string.format('[[File:%s_(3).png|link=%s]]', potion, potion)) -- file cell
            -- this uses string.format, which is a very useful function to prevent repeatedly concatenating strings (which can be a slow operation)
            -- essentially, each time you see %s in the string, that will be replaced by the corresponding value from the rest of the arguments (in this case we have 2 %s's and they're replaced by the value of gherb both times)
            -- string.format has a lot more complexities but that is a task for the full documentation to explain
            :done()
            :tag('td')
                :wikitext('[['..potion..']]') -- could use format but for 2 concats/1 subst, probably doesn't matter enough
            :done()
            -- nothing special about these
            :tag('td')
                :wikitext(v.level)
            :done()
            :tag('td')
                :wikitext(v.experience)
            :done()
            :tag('td')
                :wikitext('[[File:Herblore.png|20px|frameless|link=Herblore]] level')

            :done()
            :tag('td')
            	:wikitext(herbprice)
                -- pass this in to the coins helper function defined below, so that we get the value formatted with the coins image
            :done()
            :tag('td')
            	:wikitext('[[File:Herblore.png|20px|frameless|link=Herblore]] level')
            :done()
            :tag('td')
                :wikitext(secondaryprice)
     
            :done()
            :tag('td')
                :wikitext(profit)
            :done()
            :tag('td')
                :wikitext(gpxp)
            :done()


    end
    -- NB ipairs is used to loop array-tables where the keys are integers from 1 to n with no gaps
    -- to loop a map-table, use pairs
    -- be aware that ipairs guarantees the order is preserved, while pairs does not guarantee an order

    -- make sure to return the table we created
    return t
    -- we can call tostring on t if we wanted to, but this will be done automatically when going back from lua to wikitext
end
--[======[
    STEP 3
    return the main variable
--]======]
return p
-- in modern mediawiki, nowiki needs to be closed to be effective
-- </nowiki>