Module:Sandbox/User:BlackHawk: Difference between revisions

From WIDEVERSE Wiki
Jump to navigation Jump to search
mNo edit summary
 
m (1 revision imported)
 
(No difference)

Latest revision as of 21:23, 4 November 2021

Documentation for this module may be created at Module:Sandbox/User:BlackHawk/doc

-- <nowiki>
local p = {}

local params = require('Module:Paramtest')
local lang = mw.language.getContentLanguage()
local curr_image = require('Module:Currency Image')
local exchange = require('Module:Exchange')
local yesno = require('Module:Yesno')
local geprice = exchange._price
local f_gealch = exchange._highalch
local _gealch = '<span class="dropsline-gealch" style="margin-left:0.3em;">[[File:High_Level_Alchemy_icon.png|link=High Level Alchemy|frameless|20px]]</span>'
local _altval = '<span class="dropsline-altval" style="margin-left:0.3em;">[[File:AltValue.png|link=|frameless|20px]]</span>'
local ptitle = mw.title.getCurrentTitle()
local ns = ptitle.nsText
local title = ptitle.fullText
local pgTitle = ptitle.text

local _priceStrings = {
    sell = "Shop sells for %s %s each.",
    sellF = "Free sample",
    buy = "Shop buys for %s %s each.",
    ge = "%s coin%s each",
    geP = "%s coin%s per pack; this is the total for all the items in the pack",
    alch = "%s coin%s each; this is the high alchemy value as this item cannot be traded on the Grand Exchange.",
    alchP = "%s coin%s per pack; this is the total high alchemy value of all the items in the pack as they cannot be traded on the Grand Exchange.",
    alt = "%s %s each; this item has a distinct value, even though it cannot be traded on the Grand Exchange or be alchemised.",
    res = "%s %s total",
    resEqu = "%s coin%s per %s",
    resOne = "%s %s each. Infinite stock available",
    resErr = "%s %s each. Error: Stock provided was not a number"
}

local smwData = nil
function getSMWInfo(item)
    if smwData ~= nil then
        return smwData
    end
    local smw = mw.smw.ask({
        '[['..item..']]',
        '?High Alchemy value',
        '?Is members only'
    })
    if smw and smw[1] then
        smwData = {
            alch = smw[1]['High Alchemy value'],
            members = smw[1]['Is members only']
        }
    else
        smwData = false
    end
    return smwData
end

function commas(n)
    if tonumber(n) then
        return lang:formatNum(tonumber(n))
    else
        return n
    end
end

-- function to get the currency image and name (singular vs plural)
function currencyInfo(currency,price)
    price = tostring(price)
    -- body
    local lowcur = string.lower(currency)
    local clean = price:gsub('%W','')
    local retcur, img
    if tonumber(clean) and tonumber(clean) ~= 1 then
        retcur = currency
    else
        if lowcur == 'zemomark' or lowcur == 'tokkul' or lowcur == 'teci' then
            retcur = currency
        elseif lowcur == 'pieces of eight' then
            retcur = 'piece of eight'
        else
            retcur = string.sub(currency,1,(string.len(currency)-1))
        end
    end
    img = curr_image(currency,price) or 'AltValue.png'
    img = '<span class="dropsline-altval style="margin-left:0.3em;">[[File:'..img..'|link=|frameless|20px]]</span>'
    return img, retcur
end

function buysell(value)
    if not tonumber(value) then
        local val = yesno(value, value)
        if type(val) == 'boolean' then
            value = val
        else
            val = string.lower(val)
            if val == 'not sold' or
                val == 'not bought' or
                val == 'none' or
                val== 'n/a' then
                value = 'not'
            end
        end
    end

    return value
end

function p.main(frame)
	local args = frame:getParent().args
	local tempArgs = frame.args
	-- Params and defaults

	local name, namenotes, stock, sell, sellnotes, buy, altcur, pack, packNum = params.defaults{
			{args.Name,'Item'},
			{args.Namenotes,''},
			{args.Stock,'Unknown'},
			{args.Sell,'0'},
			{args.Sellnotes,''},
			{args.Buy,'0'},
			{args.AltCurrency,''},
            {args.Pack, ''},
            {args.PackNum, '50'}
		}
		
	-- Special cases for non-standard Arc buy prices.
	local buy1
    if params.has_content(args.Buy1) then
        buy1 = args.Buy1
    end
    local buy2
    if params.has_content(args.Buy2) then
        buy2 = args.Buy2
    end
    
	local displayname = params.default_to(args.DisplayName,name)
	local gemwname = params.default_to(args.gemwname,args.Pack)
    gemwname = gemwname or name
    local arc = yesno(tempArgs.Arc or 'no', false)
    local currency = params.default_to(tempArgs.Currency,args.Currency)
    currency = currency or ''
    -- Override currency from table head with currency set on line
    if params.has_content(args.Currency) then
        currency = args.Currency
    end
    local nosmw
    if params.has_content(args.nosmw) then
        nosmw = true
    end
    if params.has_content(tempArgs.nosmw) then
        nosmw = true
    end
    -- Override for historical (removed items)
    local historical = false
    if params.has_content(args.Historical) then
        historical = yesno(args.Historical,false)
    end
    if params.has_content(tempArgs.Historical) then
        historical = yesno(tempArgs.Historical,false)
    end

    -- Check pack number
    if not tonumber(packNum) then
        packNum = '50'
    end

	-- Remove version number from potions, enchanted jewellery, waterskins etc for smw
	local cleanedName
	local dropVers = ''
	if gemwname:match(' %(%d%)$') then
		cleanedName, dropVers = mw.ustring.match(gemwname, '^(.-) (%(%d%))$')
    elseif gemwname:match('%#') then
        cleanedName, dropVers = mw.ustring.match(gemwname, '^(.-)%#([%w%s%(%)_]+)$')
    else
        cleanedName = mw.ustring.gsub(gemwname, ' %(%d%)$', '')
    end
    cleanedName = mw.text.trim(cleanedName)
    dropVers = mw.text.trim(dropVers)
    
    local smwname = cleanedName 
    if dropVers ~= '' then
        -- get subobject instead
        smwname = cleanedName..'#'..dropVers
    end
    
    stock = mw.ustring.lower(stock)
	local gemw = true
    if params.has_content(tempArgs.gemw) then
        gemw = yesno(tempArgs.gemw or 'yes', false)
    end
    if yesno(args.gemw) ~= nil then
        gemw = yesno(args.gemw)
    end
	local alch = yesno(args.alch or 'yes', false)
	
	local hasAltCur = false
	if params.has_content(altcur) and mw.ustring.lower(altcur) ~= 'coins' then
		hasAltCur = true
	end
	
	-- Test for existance of alch value
    local hasmwalch, smwalchval
    local valueInfo = {
        alch = {
            has = false,
            value = 0,
            from = nil
        },
        ge = {
            has = false,
            value = 0,
            from = nil
        }
    }
    
    if alch then
        if gemw then
            -- does not have no-ge override
            -- lookup in GEMW
            local hasgealch, gealchval = pcall(f_gealch,gemwname)
        -- alch is not disabled
            if hasgealch then
            	if gealchval > -1 then
	                -- has a alch value from GEMW
                    if #pack > 0 then
                        gealchval = tonumber(gealchval) * tonumber(packNum)
                    end
	                valueInfo.alch = {
	                    has = true,
	                    value = tonumber(gealchval),
	                    from = 'ge'
	                }
                end
            end
        end
        if not valueInfo.alch.has then
            -- failed to find alch in GEMW or has no-ge override
            -- lookup in SMW
            local smwret = getSMWInfo(smwname)
            if smwret and smwret.alch ~= nil then
                -- alch is defined, use it
                if #pack > 0 then
                    smwret.alch = tonumber(smwret.alch) * tonumber(packNum)
                end
                valueInfo.alch = {
                    has = true,
                    value = smwret.alch,
                    from = 'smw'
                }
            elseif args.AltValue then
                --AltValue set, no alch from GE or SMW, use alt as regular alch
                valueInfo.alch = {
                    has = true,
                    value = tonumber(args.AltValue),
                    from = 'alt'
                }
                if hasAltCur then
                    valueInfo.alch.curr = altcur
                end
            else
            	alch = false
            end
        end
    else
        -- alch is disabled
        if args.AltValue then
            --Altvalue set, no alch value
            valueInfo.alch = {
                has = true,
                value = tonumber(args.AltValue),
                from = 'alt'
            }
            if hasAltCur then
                valueInfo.alch.curr = altcur
            end
        end
    end
    -- Test for existence of an exchange page
    if gemw then
        local hasgemw, gepric = pcall(geprice,gemwname)
        if hasgemw then
            if #pack > 0 then
                gepric = tonumber(gepric) * tonumber(packNum)
            end
            valueInfo.ge = {
                has = true,
                value = gepric,
                from = 'ge'
            }
        else
            valueInfo.ge = {
                has = true,
                value = valueInfo.alch.value,
                from = 'alch'
            }
            if valueInfo.alch.curr then
                valueInfo.ge.curr = valueInfo.alch.curr
            end
            if valueInfo.alch.from == 'alt' then
                valueInfo.ge.from = 'alt'
            end
        end
    elseif args.AltValue then
        valueInfo.ge = {
            has = true,
            value = tonumber(args.AltValue),
            from = 'alt'
        }
        if hasAltCur then
            valueInfo.ge.curr = altcur
        end
    elseif alch then
        valueInfo.ge = {
            has = true,
            value = valueInfo.alch.value,
            from = 'alch'
        }
        if valueInfo.alch.curr then
            valueInfo.ge.curr = valueInfo.alch.curr
        end
    end
    
    -- Use 'File:<name>.png' if no image param
	-- Use 'File:<image>' if image param; image param will include extension
	local image,image_n
	image_n = params.default_to(args.Image, name .. '.png')
	image_n = mw.ustring.gsub(image_n, '#.+$', '.png')
	if image_n:lower() == 'no' or params.is_empty(args.Name) then
		image = ''
	else
		image = mw.ustring.format('[[File:%s|link=%s|alt=%s: %s sells %s of %s for %s and buys them for %s]]', image_n, name, image_n, title, stock, name, sell, buy)
	end
	
	-- Table row
	local ret
	if arc then
		currency = 'Chimes'
		ret =  p._arc{ name,displayname,namenotes,
			stock,sell,sellnotes,buy,buy1,buy2,currency,
            pack,packNum,
			image,
			valueInfo,gemw,alch,
			tempArgs,
			cleanedName,dropVers,smwname,historical,nosmw }
	else
		ret =  p._main{ name,displayname,namenotes,
			stock,sell,sellnotes,buy,currency,
            pack,packNum,
			image,
			valueInfo,gemw,alch,
			tempArgs,
			cleanedName,dropVers,smwname,historical,nosmw }
	end

	return ret
end

-- main function to generate the row
function p._main(...)
	local name,displayname,namenotes,
		stock,sell,sellnotes,buy,currency,
        pack,packNum,
		image,
		valueInfo,gemw,alch,
		tempArgs,
		cleanedName,dropVers,smwname,historical,nosmw = unpack(...)

    -- Stock display
    local stockSort, stockDisp, stockTtl
    local infStock = false
    stock = string.lower(string.gsub(stock, ',', ''))
    if stock == '∞' or stock == 'inf' or stock == 'infinite' then
        stockSort = '10e99'
        stockTtl = 'Infinite available'
        stockDisp = '<span style="font-size:120%;">∞</span>'
        infStock = true
    elseif tonumber(stock) then
        stockSort = stock
        stockTtl = 'Base stock of '..stock
        stockDisp = commas(tonumber(stock))
    else
        stockSort = -1
        stockTtl = 'Invalid stock of '..stock..'was provided'
        stockDisp = '<span style="color:#FF0000; border-bottom:1px dashed; font-weight:bold;">Error</span>'
    end

    -- Correct currencies
    if not currency or currency == '' then
        currency = 'coins'
    end
    if not valueInfo.ge.curr or valueInfo.ge.curr == '' then
        valueInfo.ge.curr = 'coins'
    end

    -- Clean buy, sell values
    buy = buysell(buy)
    sell = buysell(sell)

    -- Sell, buy Display
    local sellDisp, sellSort, sellTtl, buyDisp, buySort, buyTtl
    local sellNum, buyNum
    if tonumber(sell) and tonumber(sell) == 0 then
        sellNum = 0
        sellSort = sellNum
        sellTtl = _priceStrings.sellF
        sellDisp = 'Free'
    elseif tonumber(sell) then
        sellNum = tonumber(sell)
        sellSort = sellNum
        local sImg, sCur = currencyInfo(currency,sellNum)
        sellTtl = mw.ustring.format(_priceStrings.sell,commas(sellNum),sCur)
        sellDisp = commas(sellNum)..sImg
    elseif sell == 'not' or sell == false then
        sellSort = -1
        sellTtl = 'This item is not sold by this shop'
        sellDisp = 'Not sold'
    else
        sellSort = tonumber('10e99')
        sellTtl = 'Sell price entered is invalid or none was given.'
        sellDisp = '<span style="color:#FF0000; border-bottom:1px dashed; font-weight:bold;">Error</span>'
    end
    if tonumber(buy) then
        buyNum = tonumber(buy)
        buySort = buyNum
        local bImg, bCur = currencyInfo(currency,buyNum)
        buyTtl = mw.ustring.format(_priceStrings.buy,commas(buyNum),bCur)
        buyDisp = commas(buyNum)..bImg
    elseif buy == 'not' or buy == false then
        buySort = -1
        buyTtl = 'This item cannot be sold to this shop'
        buyDisp = 'Not bought'
    else
        buySort = tonumber('10e99')
        buyTtl = 'Buy price entered is invalid or none was given.'
        buyDisp = '<span style="color:#FF0000; border-bottom:1px dashed; font-weight:bold;">Error</span>'
    end

    -- GE value and display
    local geSort, geDisp, geTtl
    local geImg, geCur = currencyInfo(valueInfo.ge.curr,valueInfo.ge.value)
    if valueInfo.ge.from == 'ge' then
        geSort = valueInfo.ge.value
        if #pack > 0 then
            geTtl = mw.ustring.format(_priceStrings.geP,commas(valueInfo.ge.value),lang:plural(valueInfo.ge.value or 0, '', 's'))
        else
            geTtl = mw.ustring.format(_priceStrings.ge,commas(valueInfo.ge.value),lang:plural(valueInfo.ge.value or 0, '', 's'))
        end
        geDisp = commas(valueInfo.ge.value)..geImg
    elseif valueInfo.ge.from == 'alch' then
        geSort = valueInfo.ge.value
        if #pack > 0 then
            geTtl = mw.ustring.format(_priceStrings.alchP,commas(valueInfo.ge.value),lang:plural(valueInfo.ge.value or 0, '', 's'))
        else
            geTtl = mw.ustring.format(_priceStrings.alch,commas(valueInfo.ge.value),lang:plural(valueInfo.ge.value or 0, '', 's'))
        end
        geDisp = commas(valueInfo.ge.value).._gealch
    elseif valueInfo.ge.from == 'alt' then
        geSort = valueInfo.ge.value - tonumber('10e10')
        geTtl = mw.ustring.format(_priceStrings.alt,commas(valueInfo.ge.value),geCur)
        geDisp = commas(valueInfo.ge.value)..geImg.._altval
    else
        -- No GE
        geSort = 0 - tonumber('10e99')
        geTtl = 'Item cannot be sold or alchemised'
        geDisp = 'N/A'
    end
	
	-- Resale value cell contents
	-- Resale = 0 if currencies don't match
	local resale, resaleSort, resaleDisp, resaleTtl
    local difCur = false
	if valueInfo.ge.has and valueInfo.ge.value and sellNum then
        if valueInfo.ge.curr == currency then
            resale = valueInfo.ge.value - sellNum
            if tonumber(stock) and not infStock then
                resale = stock * resale
            end
        else
            resale = valueInfo.ge.value / sellNum
            resale = math.floor((resale * 100) + 0.5) / 100
            difCur = true
		end
    end
    if tonumber(resale) and difCur then
        local sinImg, sinCur = currencyInfo(currency,1)
        local resImg, resCur = currencyInfo('coins',resale)
        resaleSort = resale - tonumber('10e10')
        resaleTtl = mw.ustring.format(_priceStrings.resEqu,commas(resale),lang:plural(resale or 0, '', 's'),sinCur)
        resaleDisp = commas(resale)..resImg..'/'..sinImg
    elseif tonumber(resale) and infStock then
        local resImg, resCur = currencyInfo(currency,resale)
        resaleSort = tonumber('10e99')
        resaleTtl = mw.ustring.format(_priceStrings.resOne,commas(resale),resCur)
        resaleDisp = mw.ustring.format('<span style="font-size:120%%;">∞</span> (%s)%s',commas(resale),resImg)
    elseif tonumber(resale) and tonumber(stock) then
        local resImg, resCur = currencyInfo(currency,resale)
        resaleSort = resale
        resaleTtl = mw.ustring.format(_priceStrings.res,commas(resale),resCur)
        resaleDisp = commas(resale)..resImg
    elseif tonumber(resale) then
        local resImg, resCur = currencyInfo(currency,resale)
        resaleSort = 0 - tonumber('10e97')
        resaleTtl = mw.ustring.format(_priceStrings.resErr,commas(resale),resCur)
        resaleDisp = mw.ustring.format('<span style="color:#FF0000; border-bottom:1px dashed; font-weight:bold;">%s%s</span>',commas(resale),resImg)
    elseif difCur then
        resaleSort = 0 - tonumber('10e98')
        resaleTtl = 'Cost and value are different currencies'
        resaleDisp = 'N/A'
    else
        resaleSort = 0 - tonumber('10e99')
        resaleTtl = 'Item is not tradeable or alchable and no value was provided'
        resaleDisp = 'N/A'
    end
    
    local ret = mw.html.create('tr')
    		
            -- inventory image
            :tag('td')
                :css('text-align','center')
                :addClass('inventory-image')
                :wikitext(image)
            :done()
            -- item name
            :tag('td')
                :css('text-align','left')
                :addClass('item-col')
                :wikitext(string.format('[[%s|%s]]%s',name,displayname,#namenotes > 3 and namenotes or ''))
            :done()
            -- stock
            :tag('td')
                :css('text-align','center')
                :addClass('stock-col')
                :attr({
                    ['data-sort-value'] = stockSort,
                    ['title'] = stockTtl
                })
                :wikitext(stockDisp)
            :done()
            -- sell price
            :tag('td')
                :css({
                    ['text-align'] = 'right',
                    cursor = 'help'
                })
                :addClass('sell-col')
                :addClass('ref-left')
                :attr({
                    ['data-sort-value'] = sellSort,
                    ['title'] = sellTtl
                })
                :wikitext(string.format('%s%s',#sellnotes > 3 and sellnotes or '',sellDisp))
            :done()
            -- buy price
            :tag('td')
                :css({
                    ['text-align'] = 'right',
                    cursor = 'help'
                })
                :addClass('buy-col')
                :attr({
                    ['data-sort-value'] = buySort,
                    ['title'] = buyTtl
                })
                :wikitext(buyDisp)
            :done()
            -- ge price
            :tag('td')
                :css({
                    ['text-align'] = 'right',
                    cursor = 'help'
                })
                :addClass('ge-column')
                :attr({
                    ['data-sort-value'] = geSort,
                    ['title'] = geTtl
                })
                :wikitext(geDisp)
            :done()
            -- resale value
            :tag('td')
                :css({
                    ['text-align'] = 'right',
                    cursor = 'help'
                })
                :addClass('resale-col')
                :attr({
                    ['data-sort-value'] = resaleSort,
                    ['title'] = resaleTtl
                })
                :wikitext(resaleDisp)
            :done()
    --Add class if line but not table is historical    
    if historical and not yesno(tempArgs.Historical,false) then
    	ret:addClass('storeline-hist')
    end

    -- SMW
    if ns == '' and not nosmw then
        local smw = {}
        local smw_sub = {}
        local source = pgTitle
        local smwNameNote = mw.text.killMarkers(namenotes)
        local smwSellNote = mw.text.killMarkers(sellnotes)
        --add function to reduce image to File:Some name.png
        if historical then
        	smw['Sells item hist'] = name
        	smw_sub = {['Sold by hist'] = source, ['Sold item image'] = mw.text.encode(image), ['Sold item hist'] = name, ['Sold item text']=displayname, ['Sold item notes']=smwNameNote, ['Store stock']=tonumber(stock), ['Store sell price']=sell, ['Store sell notes']=smwSellNote, ['Store buy price']=buy, ['Store currency']=currency}
        else
        	smw['Sells item'] = name
        	smw_sub = {['Sold by'] = source, ['Sold item image'] = mw.text.encode(image), ['Sold item'] = name, ['Sold item text']=displayname, ['Sold item notes']=smwNameNote, ['Store stock']=tonumber(stock), ['Store sell price']=sell, ['Store sell notes']=smwSellNote, ['Store buy price']=buy, ['Store currency']=currency}
        end
        if infStock then
        	smw_sub['Store stock infinite'] = true
        	smw_sub['Store stock'] = nil
        end
        if #pack > 0 and historical then
            smw_sub['Pack of hist'] = pack
            smw_sub['Pack amount'] = packNum
        elseif #pack > 0 then
        	smw_sub['Pack of'] = pack
            smw_sub['Pack amount'] = packNum
        end
        mw.smw.subobject(smw_sub, smwname .. ' ' .. stock .. ' ' .. sell) -- add item subobject to page
        mw.smw.set(smw) -- add data to page
    end

    return tostring(ret)
end

-- main function to generate the row
function p._arc(...)
	local name,displayname,namenotes,
		stock,sell,sellnotes,buy,buy1,buy2,currency,
        pack,packNum,
		image,
		valueInfo,gemw,alch,
		tempArgs,
		cleanedName,dropVers,smwname,historical,nosmw = unpack(...)

    -- Stock display
    local stockSort, stockDisp, stockTtl
    local infStock = false
    stock = string.lower(string.gsub(stock, ',', ''))
    if stock == '∞' or stock == 'inf' or stock == 'infinite' then
        stockSort = '10e99'
        stockTtl = 'Infinite available'
        stockDisp = '<span style="font-size:120%;">∞</span>'
        infStock = true
    elseif tonumber(stock) then
        stockSort = stock
        stockTtl = 'Base stock of '..stock
        stockDisp = commas(tonumber(stock))
    else
        stockSort = -1
        stockTtl = 'Invalid stock of '..stock..'was provided'
        stockDisp = '<span style="color:#FF0000; border-bottom:1px dashed; font-weight:bold;">Error</span>'
    end

    -- Correct currencies
    if not currency or currency == '' then
        currency = 'coins'
    end
    if not valueInfo.ge.curr or valueInfo.ge.curr == '' then
        valueInfo.ge.curr = 'coins'
    end

    -- Clean buy, sell values
    buy = buysell(buy)
    sell = buysell(sell)
    
    -- Sell, buy Display
    local sellDisp, sellSort, sellTtl, buyDisp, buySort, buyTtl
    local sellNum, buyNum
    local buy1Disp, buy1Sort, buy1Ttl, buy2Disp, buy2Sort, buy2Ttl
    if tonumber(sell) and tonumber(sell) == 0 then
        sellNum = 0
        sellSort = sellNum
        sellTtl = _priceStrings.sellF
        sellDisp = 'Free'
    elseif tonumber(sell) then
        sellNum = tonumber(sell)
        sellSort = sellNum
        local sImg, sCur = currencyInfo(currency,sellNum)
        sellTtl = mw.ustring.format(_priceStrings.sell,commas(sellNum),sCur)
        sellDisp = commas(sellNum)..sImg
        buyNum = tonumber(sell)
        buySort = math.floor(buyNum * 0.1)
        buy1Sort = math.floor(buyNum * 0.11)
        buy2Sort = math.floor(buyNum * 0.12)
        local bImg, bCur = currencyInfo(currency,buySort)
        buyTtl = mw.ustring.format(_priceStrings.buy,commas(buySort),bCur)
        buy1Ttl = mw.ustring.format(_priceStrings.buy,commas(buy1Sort),bCur)
        buy2Ttl = mw.ustring.format(_priceStrings.buy,commas(buy2Sort),bCur)
        buyDisp = commas(buySort)..bImg
        buy1Disp = commas(buy1Sort)..bImg
        buy2Disp = commas(buy2Sort)..bImg
    elseif sell == 'not' or sell == false then
        sellSort = -1
        sellTtl = 'This item is not sold by this shop'
        sellDisp = 'Not sold'
    else
        sellSort = tonumber('10e99')
        sellTtl = 'Sell price entered is invalid or none was given.'
        sellDisp = '<span style="color:#FF0000; border-bottom:1px dashed; font-weight:bold;">Error</span>'
    end
	if tonumber(buy) and tonumber(buy) ~= 0 then
		buyNum = tonumber(buy)
		buySort = math.floor(buyNum)
		
        -- To handle the static buy values of The Junk of One Cyclops, give the prices as buy1 and buy2. Otherwise, calculate as usual based on base buy value.
        if tonumber(buy1) then
        	buy1Sort = math.floor(buy1)
        else
        	buy1Sort = math.floor(buyNum * 1.1)
        end
        if tonumber(buy2) then
        	buy2Sort = math.floor(buy2)
        else
        	buy2Sort = math.floor(buyNum * 1.2)
        end
        
		local bImg, bCur = currencyInfo(currency,buyNum)
		buyTtl = mw.ustring.format(_priceStrings.buy,commas(buySort),bCur)
		buy1Ttl = mw.ustring.format(_priceStrings.buy,commas(buy1Sort),bCur)
		buy2Ttl = mw.ustring.format(_priceStrings.buy,commas(buy2Sort),bCur)
		buyDisp = commas(buySort)..bImg
		buy1Disp = commas(buy1Sort)..bImg
		buy2Disp = commas(buy2Sort)..bImg
	elseif buy == 'not' or buy == false then
		buySort = -1
		buy1Sort, buy2Sort = buySort, buySort
		buyTtl = 'This item cannot be sold to this shop'
		buy1Ttl, buy2Ttl = buyTtl, buyTtl
		buyDisp = 'Not bought'
		buy1Disp, buy2Disp = buyDisp, buyDisp
    end

    local ret = mw.html.create('tr')
            -- inventory image
            :tag('td')
                :css('text-align','center')
                :addClass('inventory-image')
                :wikitext(image)
            :done()
            -- item name
            :tag('td')
                :css('text-align','left')
                :addClass('item-col')
                :wikitext(string.format('[[%s|%s]]%s',name,displayname,#namenotes > 3 and namenotes or ''))
            :done()
            -- stock
            :tag('td')
                :css('text-align','center')
                :addClass('stock-col')
                :attr({
                    ['data-sort-value'] = stockSort,
                    ['title'] = stockTtl
                })
                :wikitext(stockDisp)
            :done()
            -- sell price
            :tag('td')
                :css({
                    ['text-align'] = 'right',
                    cursor = 'help'
                })
                :addClass('sell-col')
                :addClass('ref-left')
                :attr({
                    ['data-sort-value'] = sellSort,
                    ['title'] = sellTtl
                })
                :wikitext(string.format('%s%s',#sellnotes > 3 and sellnotes or '',sellDisp))
            :done()
            -- buy price
            :tag('td')
                :css({
                    ['text-align'] = 'right',
                    cursor = 'help'
                })
                :addClass('buy-col')
                :attr({
                    ['data-sort-value'] = buySort,
                    ['title'] = buyTtl
                })
                :wikitext(buyDisp)
            :done()
            -- buy (upgrade 1) price
            :tag('td')
                :css({
                    ['text-align'] = 'right',
                    cursor = 'help'
                })
                :addClass('buy1-col')
                :attr({
                    ['data-sort-value'] = buy1Sort,
                    ['title'] = buy1Ttl
                })
                :wikitext(buy1Disp)
            :done()
            -- buy (upgrade 2) value
            :tag('td')
                :css({
                    ['text-align'] = 'right',
                    cursor = 'help'
                })
                :addClass('buy2-col')
                :attr({
                    ['data-sort-value'] = buy2Sort,
                    ['title'] = buy2Ttl
                })
                :wikitext(buy2Disp)
            :done()
	--Add class if line but not table is historical    
    if historical and not yesno(tempArgs.Historical,false) then
    	ret:addClass('storeline-hist')
    end

    -- SMW
    if ns == '' and not nosmw then
        local smw = {}
        local smw_sub = {}
        local source = pgTitle
        local smwNameNote = mw.text.killMarkers(namenotes)
        local smwSellNote = mw.text.killMarkers(sellnotes)
        --add function to reduce image to File:Some name.png
        if historical then
        	smw['Sells item hist'] = name
        	smw_sub = {['Sold by hist'] = source, ['Sold item image'] = mw.text.encode(image), ['Sold item hist'] = name, ['Sold item text']=displayname, ['Sold item notes']=smwNameNote, ['Store stock']=tonumber(stock) or tonumber("10e99"), ['Store sell price']=sell, ['Store sell notes']=smwSellNote, ['Store buy price']=buy, ['Store currency']=currency}
        else
        	smw['Sells item'] = name
        	smw_sub = {['Sold by'] = source, ['Sold item image'] = mw.text.encode(image), ['Sold item'] = name, ['Sold item text']=displayname, ['Sold item notes']=smwNameNote, ['Store stock']=tonumber(stock) or tonumber("10e99"), ['Store sell price']=sell, ['Store sell notes']=smwSellNote, ['Store buy price']=buy, ['Store currency']=currency}
        end
        if infStock then
        	smw_sub['Store stock infinite'] = true
        	smw_sub['Store stock'] = nil
        end
        if #pack > 0 and historical then
            smw_sub['Pack of hist'] = pack
            smw_sub['Pack amount'] = packNum
        elseif #pack > 0 then
        	smw_sub['Pack of'] = pack
            smw_sub['Pack amount'] = packNum
        end
        mw.smw.subobject(smw_sub, smwname .. ' ' .. stock .. ' ' .. sell) -- add item subobject to page
        mw.smw.set(smw) -- add data to page
    end

    return tostring(ret)
end

return p
-- </nowiki>