Module:Bazaar

-- local getArgs = require('Module:Arguments').getArgs local loader = require('Module:Loader')

local string, table, yesno = loader.require('String', 'Table', 'Yesno') local bazaarData, aliases, i18n = loader.loadData('Bazaar/Data', 'Bazaar/Aliases', 'Bazaar/i18n')

local formatCoins = require('Module:Currency')._coins local _error = require('Module:String').error local makeColor = require('Module:Color')._colorTemplates

local p = {}

local priceTypeAliases = { buy = 'buy', b = 'buy', higher = 'buy', sell = 'sell', s = 'sell', ['lower'] = 'sell', }

-- Allows converting item name into productId

-- Allows normal minecraft names using aliases function p._getProductId(productId) -- Allow "Ench" shorthand - replaced with capital as it's needed encase alias isn't used productId = productId:gsub("[Ee][Nn][Cc][Hh][Aa]?[Nn]?[Tt]?[Ee]?[Dd]?", "ENCHANTED") return aliases[productId:lower] or productId end

function p._getProduct(productId) productId = p._getProductId(productId) return bazaarData["products"][productId]; end

local function shortenNum(num) if num == nil then return 0 end if num >= 10000 then return math.ceil(num) else return math.ceil(num*10)/10 end end

-- Invokes function p.getProductId(frame) local args = getArgs(frame) return p._getProductId(args[1]) end

local lang = mw.language.getContentLanguage

-- Invokes function p.getLastUpdatedDate -- local args = getArgs(frame) return lang:formatDate( 'd F Y, h:i a', "@"..bazaarData["last_updated"], false ) .. " UTC" -- return bazaarData["last_updated"] end

function p.lastUpdatedIcon return string.makeTitle('ⓘ', 'Values updated every half hour from hypixel api. Last updated on: ' .. p.getLastUpdatedDate) end

-- Invokes function p.calcMaterialBuyPrices(frame) local args = getArgs(frame) local lang = mw.language.getContentLanguage

local price_type = args["type"] or args["t"] local coin = yesno(args["coin"] or args["c"], true) local not_including = args["not_including"] -- first combine both methods of entering data into one list local stringstocalc = {} for i = 1,16,1 do	   if i==1 and string.find(args[1], "\*")==1 then local splitwikilist = mw.text.split(string.sub(args[1], 2), "%s*\*%s*"); for i, li in pairs(splitwikilist) do	          stringstocalc[#stringstocalc+1] = li	        end else stringstocalc[#stringstocalc+1] = args[i] end end -- parse the paramaters into usable values local items = {} for i, item in pairs(stringstocalc) do       local numOrNil = tonumber(lang:parseFormattedNumber(item)) if numOrNil then items[#items+1] = numOrNil else local num, name = mw.ustring.match(item, "([%d,%.]+)x? %[?%[?([^%[%]]+)%|?.*%]?%]?") if not num then -- also test for format name, num = mw.ustring.match(item, "([^%[%]%,]+)%s*,%s*([%d]+)") if not num then return _error('Invalid item format: '..item) end end items[#items+1] = {name, tonumber(lang:parseFormattedNumber(num))} end end return p._calcMaterialBuyPrices(items, price_type, coin, not_including) end

function p._calcMaterialBuyPrices(entries, price_type, coin, not_including) -- entries = [ [id,num] or num ] local total, abbr = 0, {} for i, entry in pairs(entries) do       if tonumber(entry) then total = total + tonumber(entry) else local product = p._getProduct(entry[1]); if not product then return _error('Invalid product ID %q', entry[1]) end local prodName = i18n[p._getProductId(entry[1])] or string._ucfirst(p._getProductId(entry[1])):gsub('_',' ') table.merge(abbr, ('%dx %s'):format(entry[2], prodName)) -- default to buy, but allow "sell" as an option price_type = priceTypeAliases[price_type] or 'buy' total = total + (product[price_type] * entry[2]) end end not_including = not_including and (' (not including: %s)'):format(not_including) or '' if coin then local ret = tostring(formatCoins(shortenNum(total))) local temp = ret:match('(.-)') if temp then temp = string.makeTitle(string.trim(temp), 'Materials used: &#10;'..table.concat(abbr, ', &#010;')) end ret = ret:gsub('<(.-)font%-variant%-numeric(.-)>.-',       	'<%1font-variant-numeric%2>'..(temp or ret)..'') return ret..not_including end return total..not_including end

-- Invokes function p.getProductData(frame) local args = getArgs(frame) local productId = args[1] local datatype = string.lower(args[2] or "buy") local long = yesno(args["long"], false) local coin = yesno(args["coin"], false) return p._getProductData(productId, datatype, long, coin) end

function p._getProductData(productId, datatype, long, coin) local product = p._getProduct(productId); if not product then return _error('Invalid product ID %q', productId) end if datatype=="buy" or datatype=="sell" then local num = product[datatype] if not long then num = shortenNum(num) end if coin then num = formatCoins(num) end return num end -- else datatype not valid return _error('Invalid data type') end

-- Invokes not function p.getPriceChange(frame) local args = getArgs(frame) local productId = args[1] local datatype = string.lower(args[2] or "buy") local format = yesno(args["format"] or args['f'], true) return p._getPriceChange(productId, datatype, format) end

function p._getPriceChange(productId, datatype, format) local product = p._getProduct(productId); if not product then return _error('Invalid product ID', productId) end if datatype=="buy" or datatype=="sell" then local num = product[datatype] local num_old = product.prev[1][datatype] local ret_num = (num - num_old) / num_old if format then local shouldAddPlus = ret_num > 0 ret_num = ret_num * 100 ret_num = string.roundNumber(ret_num, 2) if ret_num >= 25 then return makeColor('dark green', table.concat{'⇑ +', ret_num, '%'}) elseif ret_num >= 5 then return makeColor('green', table.concat{'↑ +', ret_num, '%'}) elseif ret_num <= -25 then return makeColor('dark red', table.concat{'⇓ ', ret_num, '%'}) elseif ret_num <= -5 then return makeColor('red', table.concat{'↓ ', ret_num, '%'}) else return makeColor('gray', table.concat{shouldAddPlus and '+' or '', ret_num, '%'}) end end end -- else datatype not valid return _error('Invalid data type') end

-- Invokes not function p.getPriceSpread(frame) local args = getArgs(frame) local productId = args[1] local long = yesno(args.long or args.l, false) local coin = yesno(args.coin or args.coins or args.c, false) return p._getPriceSpread(productId, long, coin) end

function p._getPriceSpread(productId, long, coin) local product = p._getProduct(productId); if not product then return _error('Invalid product ID %q', productId) end local buy = product.buy local sell = product.sell local spread = buy - sell spread = math.abs(spread) if not long then spread = shortenNum(spread) end if coin then spread = tostring(formatCoins(spread)) end return spread end return p