Module:Currency

-- local p = {}

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

local string, table, yesno = loader.require('String', 'Table', 'Yesno') local formatNum, shorten, toNumber = string._formatNum, string._formatShortNum, string._toNumber local currencyData = loader.loadData('Module:Currency/Data')

local lang = mw.language.getContentLanguage --local getBazaarPrice = require('Module:Bazaar')._getProductData -- -- access point -- function p.coins(frame) local args = getArgs(frame) if args[1] and args[1]:match(' ') then return args[1] end if args[1] then s = args[1]:lower:gsub('[%[%]]+', ):gsub('coins?', ) end local m = args[2] local useShort = yesno(args["short"] or args["s"], false) local useApproximate = yesno(args["approximate"] or args["a"], false) local useImage = yesno(args["image"] or args["i"] or args["si"] or args["show_image"], false) local noLink = yesno(args["nolink"] or args["nl"], false) local imageInFront = yesno(args["image_in_front"] or args["iif"], false) local alt = args['alt'] return p._coins(s, m, useShort, useApproximate, useImage, noLink, imageInFront, alt) end function p._coins(s, m, useShort, useApproximate, useImage, noLink, imageInFront, alt) return p._currency(s, m, {		useShort = useShort, 		useApproximate = useApproximate, 		useImage = useImage, 		noLink = noLink, 		imageInFront = imageInFront, 		alt = alt, 		currency = 'coins',	}) end -- -- access point -- function p.bits(frame) local args = getArgs(frame) if args[1] and args[1]:match(' ') then return args[1] end if args[1] then s = args[1]:lower:gsub('[%[%]]+', ):gsub('(skyblock)?bits?', ) end local m = args[2] local useShort = yesno(args["short"] or args["s"], false) local useApproximate = yesno(args["approximate"] or args['approx'] or args["a"], false) local useImage = yesno(args["image"] or args["i"] or args["si"] or args["show_image"], false) local noLink = yesno(args["nolink"] or args["nl"], false) local imageInFront = yesno(args["image_in_front"] or args["iif"], false) local alt = args['alt'] return p._bits(s, m, useShort, useApproximate, useImage, noLink, imageInFront, alt) end function p._bits(s, m, useShort, useApproximate, useImage, noLink, imageInFront, alt) return p._currency(s, m, {		useShort = useShort, 		useApproximate = useApproximate, 		useImage = useImage, 		noLink = noLink, 		imageInFront = imageInFront, 		alt = alt, 		currency = 'bits',	}) end -- -- access point -- function p.gems(frame) local args = getArgs(frame) if args[1] and args[1]:match(' ') then return args[1] end if args[1] then s = args[1]:lower:gsub('[%[%]]+', ):gsub('%s*(skyblock)?gems?', ) end local m = args[2] local useShort = yesno(args["short"] or args["s"], false) local useApproximate = yesno(args["approximate"] or args['approx'] or args["a"], false) local useImage = yesno(args["image"] or args["i"] or args["si"] or args["show_image"], false) local noLink = yesno(args["nolink"] or args["nl"], false) local imageInFront = yesno(args["image_in_front"] or args["iif"], false) local alt = args['alt'] return p._gems(s, m, useShort, useApproximate, useImage, noLink, imageInFront, alt) end function p._gems(s, m, useShort, useApproximate, useImage, noLink, imageInFront, alt) return p._currency(s, m, {		useShort = useShort, 		useApproximate = useApproximate, 		useImage = useImage, 		noLink = noLink, 		imageInFront = imageInFront, 		alt = alt, 		currency = 'gems',	}) end -- -- US$ access point -- function p.currency(frame) local args = getArgs(frame) local s = args[1] or nil if args[1] and args[1]:match(' ') then return args[1] end if s then s = args[1]:gsub('%s*([Ss]ky[Bb]lock)?', '') end local m = args[2] local useShort = yesno(args["short"] or args["s"], false) local useApproximate = yesno(args["approximate"] or args['approx'] or args["a"], false) local useImage = yesno(args["image"] or args["i"] or args["si"] or args["show_image"], false) local noLink = yesno(args["nolink"] or args["nl"], false) local imageInFront = yesno(args["image_in_front"] or args["iif"], false) local alt = args['alt'] return p._currencyTemplate(s, m, useShort, useApproximate, useImage, noLink, imageInFront, alt) end function p._currencyTemplate(s, m, useShort, useApproximate, useImage, noLink, imageInFront, alt) local curr if s:find('[Gg]ems?') then s = s:gsub('[Gg]ems?', '') curr = 'gems' elseif s:find('[Bb]its?') then s = s:gsub('[Bb]its?', '') curr = 'bits' elseif s:find('[Pp]elts?') then s = s:gsub('[Pp]elts?', '') curr = 'pelts' else s = s:gsub('[Cc]oins?', '') curr = 'coins' end return p._currency(s, m, {		useShort = useShort, 		useApproximate = useApproximate, 		useImage = useImage, 		noLink = noLink, 		imageInFront = imageInFront, 		alt = alt, 		currency = curr,	}) end

local function getImg(val, t)	if type(t) ~= 'table' then return {t} end if type(t[1]) ~= 'table' then return {t[1]} end for i,v in ipairs(t) do		if (not v.lim or v.lim == 'inf') -- no upper limit, or upper limit is inf or (i == table.length(t)) -- reached last element in table or (val < v.lim) then return v		end end end -- -- Module access point -- function p._currency(...) local s, m, options, useShort, useApproximate, useImage, noLink, imageInFront, alt, currency -- Support numbered arguments if type(({...})[3]) ~= 'table' then s, m, useShort, useApproximate, useImage, noLink, imageInFront, alt, currency = checkTypeArgs({			{ 'string', 'number', nilOk=true },			{ 'string', 'number', nilOk=true },			{ 'boolean', nilOk=true },			{ 'boolean', nilOk=true },			{ 'boolean', nilOk=true },			{ 'boolean', nilOk=true },			{ 'boolean', nilOk=true },			{ 'string', nilOk=true },		}, ...) else s, m, options = checkTypeArgs({ { 'string', 'number', nilOk=true }, { 'string', 'number', nilOk=true }, { 'table', nilOk=true } }, ...) useShort, useApproximate, useImage, noLink, imageInFront, alt, currency = options.useShort, options.useApproximate, options.useImage, options.noLink, options.imageInFront, options.alt, options.currency end if s and tostring(s):match('.+%-.+') then temp = string.split(tostring(s),"-") if (#temp == 2) then s = temp[1] m = temp[2] end end if not currency then currency = 'coins' end -- Default values useShort = useShort or false useApproximate = useApproximate or false currency = currencyData[currency] -- If first value is scientific notation if s and string.find(tostring(s), "10%^%d*") then --if not useShort, return scientific notation. if useShort, convert scientific notation to number if not useShort then s = s:gsub("%s+?%*%s+?", " × ") s = s:gsub("10%^(%d*)", "10%1") return mw.html.create('span') :css("color", currency.color) :wikitext(table.concat({ "", s, "",					currency.name,					" " }))		else if s:find("%*") then local number = s:match("(%d*)%s?*%s+?10%^%d*") local exponent = s:match("%d*%s?*%s+?10%^(%d*)") s = tonumber(number) * math.pow(10, tonumber(exponent)) else local toShort = s:match("10%^(%d*)") s = math.pow(10, tonumber(toShort)) end end -- If first value isn't a valid number, just return the invalid number as a fallthrough elseif s and toNumber(s) == nil then return s	-- If first value is null, just return colored currency text elseif s == nil then return mw.html.create('span') :css("color", currency.color) :wikitext(table.concat({ "",					alt and alt or currency.name..'s',					" " }))	end -- Convert params to numbers - nil if not a number s = toNumber(s) m = toNumber(m) local sAsNumber = s	image = '' if (useImage or imageInFront) and currency.images then local img_ = getImg(s, currency.images) image = table.concat{ ''		}		image = image..'&thinsp;' end local tooltip = nil if useShort then if m then tooltip = formatNum(s).."–"..formatNum(m) elseif s then tooltip = formatNum(s) end s = shorten(s) if m then m = shorten(m) end else s = formatNum(s) if m then m = formatNum(m) end end g = mw.html.create('span') :attr("title", tooltip) :css("font-variant-numeric", "tabular-nums") if useApproximate then g:wikitext("&#8776;") end if m then t = s.."–"..m.." " g:wikitext(t) elseif s then t = s.." " g:wikitext(t) end return mw.html.create('span') :css("color", currency.color) :wikitext(imageInFront and image or '') :node(g) :wikitext(			(imageInFront and '' or image),			"",			alt and alt or lang:plural(sAsNumber, currency.name, currency.name..'s'),			" "		) end

function p.currencySlot(s, m, noLink, noarg1) local curr if type(s) ~= 'string' then return end if s:find('[Gg]ems?%s*$') then s = s:gsub('[Gg]ems?%s*$', '') curr = 'gems' elseif s:find('[Bb]its?%s*$') then s = s:gsub('[Bb]its?%s*$', '') curr = 'bits' elseif s:find('[Pp]elts?%s*$') then s = s:gsub('[Pp]elts?%s*$', '') curr = 'pelts' elseif s:find('[Cc]oins?%s*$') then s = s:gsub('[Cc]oins?%s*$', '') curr = 'coins' else return end return p._currencySlot(s, m, {		noLink = noLink or false,		noarg1 = noarg1 or false,		currency = curr,	}) end

function p._currencySlot(...) local s, m, options, noLink, noarg1, currency -- Support numbered arguments if type(({...})[3]) ~= 'table' then s, m, noLink, noarg1, currency = checkTypeArgs({ 			{ 'string', 'number', nilOk=true },			{ 'string', 'number', nilOk=true },			{ 'boolean', nilOk=true },			{ 'boolean', nilOk=true },			{ 'string', nilOk=true },		}, ...) else s, m, options = checkTypeArgs({ { 'string', 'number', nilOk=true }, { 'string', 'number', nilOk=true }, { 'table', nilOk=true } }, ...) noLink, noarg1, currency = options.noLink, options.noarg1, options.currency end if s then temp = string.split(tostring(s),"-") if (#temp == 2) then s = temp[1] m = temp[2] end end if not currency then currency = 'coins' end currency = currencyData[currency] -- If first value is scientific notation if s and string.find(tostring(s), "10%^%d*") then --if not useShort, return scientific notation. if useShort, convert scientific notation to number if s:find("%*") then local number = s:match("(%d*)%s?*%s+?10%^%d*") local exponent = s:match("%d*%s?*%s+?10%^(%d*)") s = tonumber(number) * math.pow(10, tonumber(exponent)) else local toShort = s:match("10%^(%d*)") s = math.pow(10, tonumber(toShort)) end -- If first value isn't a valid number, return nil as conversion failed -- If first value is null, also return nil as conversion failed elseif toNumber(s) == nil then return end -- Convert params to numbers - nil if not a number s, m = toNumber(s), toNumber(m) local sAsNumber = s	image = '' local source = currency.images or currency.placeholder local item = getImg(m or s, source)[1] local grouped_num, tooltip if m then grouped_num = ('%.f-%.f'):format(s,m) tooltip = formatNum(s).."-"..formatNum(m) elseif s then grouped_num = ('%.f'):format(s) tooltip = formatNum(s) end local ret = { name = item, link = noLink and '' or currency.destPage, title = ('%s%s %s'):format(			currency.tooltipcolor, 			tooltip,			lang:plural(sAsNumber, currency.name, currency.name..'s')			), text = '', }	if not noarg1 then ret[1] = grouped_num and ('%s,%s'):format(item,grouped_num) or item end return ret end

-- Template:Coins to Dollars -- -- Used to convert value in coins to US Dollars, based on Booster Cookie prices

function p.coins_to_dollars(frame) local args = getArgs(frame) local coins = args[1] local isFormatted = yesno(args['format'] or args['f'], true) return p._coins_to_dollars(coins, type) end function p._coins_to_dollars(coins, isFormatted) if isFormatted == nil then isFormatted = true end local cookiePriceCoins = getBazaarPrice('BOOSTER_COOKIE', 'buy', true, false) --id, type, isLong, isFormatted local cookiePriceGems = 325 local cookiePriceDollars = 4.99 / 675 * cookiePriceGems local coinPriceDollars = cookiePriceCoins / cookiePriceDollars if not isFormatted then return coins / coinPriceDollars end local dollars = coins / coinPriceDollars dollars = dollars * 100 dollars = math.floor(dollars) dollars = dollars / 100 return '$'..formatNum(dollars) end

-- Template:Bits to Coins -- -- Used to convert value in cbits to coins, based on prices across items with fairly stable prices and demand

function p.bits_to_coins(frame) local args = getArgs(frame) local bits = args[1] return p._bits_to_coins(bits) end function p._bits_to_coins(bits) local coins = bits * 300 -- based on enrichments which are worth 1.5m and cost 5000 bits return p._coins(coins, nil, true, true) end

return p