Module:ExchangeDefault
Jump to navigation
Jump to search
Documentation for this module may be created at Module:ExchangeDefault/doc
-- <pre>
-- Default view for {{ExchangeItem}} for use on Exchange ns pages
--
-- Use of this via #invoke is deprecated and will eventually be removed
-- This is intended for use by [[Module:Exchange]]
--
local p = {}
-- imports
local exchange = require( 'Module:Exchange ' )
local excgdata = require( 'Module:ExchangeData' )._main
local round = require( 'Module:Number' )._round
local timeago = require( 'Module:TimeAgo' )._ago
local yesno = require( 'Module:Yesno' )
function p.main( item )
local frame = mw.getCurrentFrame()
local lang = mw.language.getContentLanguage()
local title = mw.title.getCurrentTitle()
local data = mw.loadData( 'Module:Exchange/' .. item )
local bulkData = {
price = exchange.loadBulkData(item, 'price'),
date = exchange.loadBulkData('%LAST_UPDATE_F%', 'price'),
last = exchange.loadBulkData(item, 'lastPrice'),
volume = exchange.loadBulkData(item, 'volume'),
volumeDate = exchange.loadBulkData('%LAST_UPDATE_F%', 'volume'),
}
-- set variables here if possible to keep table building easier to follow
local rowspan = 8
local volDate = bulkData.volumeDate or lang:formatDate( 'c' )
local dateDiffZ = lang:formatDate( 'z' ) - lang:formatDate( 'z', volDate )
local dateDiffY = lang:formatDate( 'Y' ) - lang:formatDate( 'Y', volDate )
local price = bulkData.price and lang:formatNum( bulkData.price ) or '<i>Unknown</i>'
local priceDiff = (bulkData.price or 0) - (bulkData.last or 0)
local priceDiffF = lang:formatNum(priceDiff) or '<i>Unknown</i>'
local priceDiffPerc = ''
local priceDiffClass = 'unchanged' --todo neutral
local priceDiffSlide = '' --todo neutral
local priceDiffIcon = 'Unchanged' --todo neutral
local itemIcon = data.icon or (( data.item or 'Coins 1000') .. '.png')
local date = '<i>Unknown</i>'
local lowAlchMultiplier = 0.4
local highAlchMultiplier = 0.6
local rawLowAlch = -1
local rawHighAlch = -1
local lowAlch = '<i>Not alchable</i>'
local highAlch = '<i>Not alchable</i>'
local memsIcon = ''
local usage = ''
if data.volume and ( dateDiffZ + 365 * dateDiffY ) <= 7 then
rowspan = 10
end
if bulkData.date then
date = lang:formatDate( 'j F Y, H:i "(UTC)"', bulkData.date )
timeagodate = bulkData.date
end
if data.alchable == nil or yesno( data.alchable ) then
if data.value then
if data.alchmultiplier then
highAlchMultiplier = data.alchmultiplier
lowAlchMultiplier = highAlchMultiplier * 2/3
end
rawLowAlch = math.max( math.floor( data.value * lowAlchMultiplier ), 1 )
rawHighAlch = math.max( math.floor( data.value * highAlchMultiplier ), 1 )
lowAlch = lang:formatNum( rawLowAlch )
highAlch = lang:formatNum( rawHighAlch )
else
lowAlch, highAlch = '<i>Unknown</i>', '<i>Unknown</i>'
end
end
if data.members ~= nil then
if data.members then
memsIcon = 'Members'
else
memsIcon = 'Free-to-play'
end
end
if priceDiff > 0 then
priceDiffClass = 'positive'
priceDiffSlide = 'slide-up'
priceDiffIcon = 'Up'
elseif priceDiff < 0 then
priceDiffClass = 'negative'
priceDiffSlide = 'slide-down'
priceDiffIcon = 'Down'
end
if bulkData.last and bulkData.last > 0 then
priceDiffPerc = round(priceDiff / bulkData.last * 100, 2) .. '%'
end
if priceDiff >= 0 then
priceDiffF = '+'..priceDiffF
priceDiffPerc = '+'..priceDiffPerc
end
-- workaround so we can use `table.concat`
usage = {}
for k, v in ipairs( data.usage ) do
usage[k] = v
end
if #usage == 0 then
usage = "\n* ''None''"
else
usage = '\n* [[' .. table.concat( usage, ']]\n* [[' ) .. ']]'
end
local noErr, chartdata = pcall( excgdata, { item }, true )
if not noErr then
chartdata = 'Chart not available'
end
-- build table
local div = mw.html.create('div')
:addClass('gemw-container')
if data.historical then
div:addClass('gemw-historical')
date = lang:formatDate( 'j F Y, H:i "(UTC)"', data.date )
timeagodate = data.date
end
--header
div :tag('div')
:addClass('gemw-header')
:addClass(priceDiffClass)
:tag('div')
:addClass('gemw-section-left')
:tag('p')
:addClass('gemw-image inventory-image')
:wikitext('[[File:'..itemIcon..'|link='..data.item..']]')
:done()
:tag('p')
:addClass('gemw-name')
:wikitext('[['..data.item..']]')
:done()
:tag('p')
:addClass('gemw-examine')
:wikitext(data.examine or '')
:done()
:tag('div')
:tag('span')
:addClass('gemw-price')
:addClass(priceDiffSlide)
:attr('id', 'GEPrice')
:wikitext(price)
:done()
:tag('span')
:addClass('gemw-change')
:addClass(priceDiffSlide..'-2')
:wikitext(priceDiffF)
:wikitext(' ')
:wikitext(priceDiffPerc)
:wikitext(' [[File:'..priceDiffIcon..'.svg|12px|link=]]')
:done()
:done()
:done()
:tag('div')
:addClass('gemw-section-right')
:tag('p')
:addClass('gemw-updated')
:attr('data-date', date) -- used by [[MediaWiki:Gadget-gemwupdate.js]]
:wikitext('Last updated ')
:tag('span')
:addClass('gemw-time')
:wikitext(timeago{timeagodate, purge='yes', purgeText='refresh'})
:done()
:tag('br'):done()
:wikitext(' on ')
:wikitext(date)
:done()
:tag('div')
:addClass('gemw-button-wrapper gemw-update-price')
:attr('id', 'gemw_guide')
:wikitext('')
:done()
:done()
:done() --close header
-- body
local dlTag = div :tag('div')
:addClass('gemw-body')
:tag('div')
:addClass('gemw-section-left')
:tag('dl')
dlTag :tag('div')
:addClass('gemw-property gemw-members')
:tag('dt')
:wikitext('Status')
:done()
:tag('dd')
:wikitext(memsIcon)
:done()
:done()
:tag('div')
:addClass('gemw-property gemw-limit')
:tag('dt')
:wikitext('[[Grand Exchange#Trade restrictions|Buy limit]]')
:done()
:tag('dd')
:attr('id', 'exchange-limit')
:wikitext(data.limit and lang:formatNum( data.limit ) or '<i>Unknown</i>' )
:done()
:done()
:tag('div')
:addClass('gemw-property gemw-id')
:tag('dt')
:wikitext('Item ID')
:done()
:tag('dd')
:attr('id', 'exchange-itemid')
:wikitext(data.itemId or '<i>Unknown</i>')
:done()
:done()
:tag('div')
:addClass('gemw-property gemw-highalch')
:tag('dt')
:wikitext('[[High Level Alchemy|High Alchemy]]')
:done()
:tag('dd')
:attr('id', 'exchange-highalch')
:wikitext(highAlch)
:done()
:done()
:tag('div')
:addClass('gemw-property gemw-lowalch')
:tag('dt')
:wikitext('[[Low Level Alchemy|Low Alchemy]]')
:done()
:tag('dd')
:attr('id', 'exchange-lowalch')
:wikitext(lowAlch)
:done()
:done()
:tag('div')
:addClass('gemw-property gemw-value')
:tag('dt')
:wikitext('[[Value]]')
:done()
:tag('dd')
:attr('id', 'exchange-value')
:wikitext(data.value and lang:formatNum( data.value ) or '<i>Unknown</i>')
:done()
:done()
:done()
:tag('div')
:tag('p')
:addClass('gemw-links')
:wikitext('External links')
:done()
:tag('div')
:addClass('gemw-button secondary')
:wikitext('[http://services.runescape.com/m=itemdb_rs/viewitem.ws?obj=' .. data.itemId .. ' Official GE database]')
:done()
:tag('div')
:addClass('gemw-button secondary')
:wikitext('[http://services.runescape.com/m=itemdb_rs/results.ws?query=' .. mw.uri.encode( item, 'QUERY' ) .. ' Related items]')
:done()
:done()
:tag('div')
:tag('p')
:addClass('gemw-links')
:wikitext('Module links')
:done()
:tag('div')
:addClass('gemw-button secondary')
:wikitext('[[Module:Exchange/' .. item .. '|Exchange info]]')
:done()
:done()
:done()
:tag('div')
:addClass('gemw-section-right gemw-chart')
:wikitext(chartdata)
:done()
if data.volume and ( dateDiffZ + 365 * dateDiffY ) <= 7 then
dlTag:tag('div')
:addClass('gemw-property gemw-volume')
:tag('dt')
:wikitext('7-day volume')
:done()
:tag('dd')
:wikitext(lang:formatNum( 1000000 * data.volume ))
:done()
end
div = tostring( div )
-- categories
local cats = ''
local natPrice
if title.nsText == 'Exchange' then
cats = cats .. '[[Category:Grand Exchange]]'
if data.historical then
cats = cats .. '[[Category:Historical Grand Exchange]]'
else
cats = cats .. '[[Category:Grand Exchange by date updated|*' .. lang:formatDate( 'c', bulkData.date ) .. data.itemId .. ']]'
end
if item ~= title.text then
cats = cats .. '[[Category:Exchange names that needs checking]]'
end
-- have to preprocess this for it to work
cats = cats .. frame:preprocess( '{{DEFAULTSORT:' .. data.item .. '}}' )
if not data.historical then
if bulkData.price and data.value and ( data.alchable == nil or yesno( data.alchable ) ) then
natPrice = exchange.loadBulkData('Nature rune', 'price')
if math.floor( ( data.value * 0.6 ) - bulkData.price - natPrice ) > 0 then
cats = cats .. '[[Category:Profitable Alchemy Items]]'
end
if math.floor( ( data.value * 0.4 ) - bulkData.price - natPrice ) > 0 then
cats = cats .. '[[Category:Profitable Low Alchemy Items]]'
end
if math.floor( ( data.value * 0.3 ) - bulkData.price ) > 0 then
cats = cats .. '[[Category:Profitable General Store Items]]'
end
elseif not data.value then
cats = cats .. '[[Category:Exchange items missing value]]'
end
if data.volume then
cats = cats .. '[[Category:Exchange items with trade volume]]'
end
end
-- this doesn't allow for the update time to be in the previous day but less than 24 hours
-- if that's the case, then the page will end up in the 7 days category
-- the same will happen for the other 2 categories too
-- but it's not so noticeable given the already elapsed time
local lastUpdate
if not data.historical then
lastUpdate = ( lang:formatDate( 'z' ) - lang:formatDate( 'z', bulkData.date ) + 365 * ( lang:formatDate( 'Y' ) - lang:formatDate( 'Y', bulkData.date ) ) + 3 ) / 7
lastUpdate = round( lastUpdate, 0 )
if lastUpdate == 1 then
cats = cats .. '[[Category:Needs price update/7 days]]'
elseif lastUpdate >= 2 and lastUpdate <= 4 then
cats = cats .. '[[Category:Needs price update/28 days]]'
elseif lastUpdate > 4 then
cats = cats .. '[[Category:Needs price update/29+ days]]'
end
if not data.limit then
cats = cats .. '[[Category:Exchange items missing limit]]'
end
if not data.category then
cats = cats .. '[[Category:Exchange items missing category]]'
end
-- Error checking
if not bulkData.price or bulkData.price < 1 then
cats = cats .. '[[Category:Exchange items with no price]]'
end
end
end
local smw_to_json_names = {
id = 'Exchange ID',
name = 'Exchange name',
limit = 'Exchange limit',
value = 'Exchange value',
isalchable = 'Exchange is alchable',
highalch = 'Exchange high alch',
lowalch = 'Exchange low alch',
info = 'Exchange module',
history = 'Exchange history module',
historical = 'Exchange is historical'
}
local smw_json = {}
local smw_data_arr = {}
smw_json.id = data.itemId
smw_json.name = item
smw_json.limit = data.limit
smw_json.value = data.value
smw_json.isalchable = data.alchable == nil or yesno( data.alchable )
if data.historical == true then
-- ensure data type correctness
smw_json.historical = true
else
smw_json.historical = false
end
if smw_json.isalchable then
smw_json.highalch = rawHighAlch
smw_json.lowalch = rawLowAlch
end
smw_json.info = 'Module:Exchange/' .. data.item
smw_json.history = 'Module:Exchange/' .. data.item .. '/Data'
for k,v in pairs(smw_to_json_names) do
smw_data_arr[v] = smw_json[k]
end
local smwJsonGood, smwJsonEncoded = pcall(mw.text.jsonEncode,smw_json)
if smwJsonGood then
smw_data_arr['Exchange JSON'] = smwJsonEncoded
else
div = div .. '<div style="display:none;">Error making JSON for SMW[[Category:SMW errors]]</div>'
end
local res = mw.smw.set(smw_data_arr)
if not res == true then
div = div .. '<div style="display:none;">Error setting SMW properties: '..res.error..'[[Category:SMW errors]]</div>'
end
return div .. cats
end
function p.exchangeItem( frame )
local fargs = frame.args
local pargs = frame:getParent().args
local item = pargs[1] or fargs.item
item = exchange.checkTitle( item )
return p.main( item )
end
return p