Module:Sandbox/User:E2 e8/Store Line Test: Difference between revisions

From WIDEVERSE Wiki
Jump to navigation Jump to search
(Created page with "-- <nowiki> local p = {} local params = require('Module:Paramtest') local lang = mw.language.getContentLanguage() local curr_image = require('Module:Currency Image') local ex...")
(No difference)

Revision as of 22:36, 24 November 2020

Documentation for this module may be created at Module:Sandbox/User:E2 e8/Store Line Test/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,
		stock, sell, buy, altcur, pack, packNum = params.defaults{
			{args.Name,'Item'},
			{args.Stock,'Unknown'},
			{args.Sell,'0'},
			{args.Buy,'0'},
			{args.AltCurrency,''},
            {args.Pack, ''},
            {args.PackNum, '50'}
		}
	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,
			stock,sell,buy,currency,
            pack,packNum,
			image,
			valueInfo,gemw,alch,
			tempArgs,
			cleanedName,dropVers,smwname,historical,nosmw }
	else
		ret =  p._main{ name,displayname,
			stock,sell,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,
		stock,sell,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]]',name,displayname))
            :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')
                :attr({
                    ['data-sort-value'] = sellSort,
                    ['title'] = sellTtl
                })
                :wikitext(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
        --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, ['Store stock']=tonumber(stock), ['Store sell price']=sell, ['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, ['Store stock']=tonumber(stock), ['Store sell price']=sell, ['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,
		stock,sell,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
    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
        -- Buy price depends on sell price, having an additional buy parameter 
        -- is both pointless and makes buy prices inaccurate
        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 = buyNum
		buy1Sort = math.floor(buyNum * 1.1)
		buy2Sort = math.floor(buyNum * 1.2)
		local bImg, bCur = currencyInfo(currency,buyNum)
		buyTtl = mw.ustring.format(_priceStrings.buy,commas(buyNum),bCur)
		buy1Ttl = mw.ustring.format(_priceStrings.buy,commas(buy1Sort),bCur)
		buy2Ttl = mw.ustring.format(_priceStrings.buy,commas(buy2Sort),bCur)
		buyDisp = commas(buyNum)..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]]',name,displayname))
            :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')
                :attr({
                    ['data-sort-value'] = sellSort,
                    ['title'] = sellTtl
                })
                :wikitext(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
        --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, ['Store stock']=tonumber(stock) or tonumber("10e99"), ['Store sell price']=sell, ['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, ['Store stock']=tonumber(stock) or tonumber("10e99"), ['Store sell price']=sell, ['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>